@ctrliq/quantic-components 1.83.0 → 1.84.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/dist/action-group/action-group.component.d.ts +13 -0
  2. package/dist/action-group/action-group.component.js +63 -0
  3. package/dist/action-group/index.d.ts +1 -0
  4. package/dist/action-group/index.js +1 -0
  5. package/dist/action-group/index.stories.d.ts +25 -0
  6. package/dist/action-group/index.stories.js +59 -0
  7. package/dist/astro.d.ts +4 -1
  8. package/dist/astro.js +4 -1
  9. package/dist/astro.js.map +1 -1
  10. package/dist/badge/badge-group.component.d.ts +13 -0
  11. package/dist/badge/badge-group.component.js +62 -0
  12. package/dist/badge/badge-group.stories.d.ts +41 -0
  13. package/dist/badge/badge-group.stories.js +62 -0
  14. package/dist/badge/index.d.ts +1 -0
  15. package/dist/badge/index.js +1 -0
  16. package/dist/button-bar/button-bar-item.d.ts +3 -0
  17. package/dist/button-bar/button-bar-item.js +12 -1
  18. package/dist/button-bar/button-bar.d.ts +9 -0
  19. package/dist/button-bar/button-bar.js +53 -2
  20. package/dist/button-bar/index.stories.js +2 -2
  21. package/dist/button-bar/index.utils.d.ts +6 -0
  22. package/dist/button-bar/index.utils.js +31 -0
  23. package/dist/button-bar/index.utils.test.d.ts +1 -0
  24. package/dist/button-bar/index.utils.test.js +53 -0
  25. package/dist/button-group/button-group.js +1 -2
  26. package/dist/capacity-bar/index.js +30 -30
  27. package/dist/card/card-carousel.component.js +35 -35
  28. package/dist/card/card-group.component.js +2 -8
  29. package/dist/card/card.component.js +38 -38
  30. package/dist/code-input/index.js +33 -33
  31. package/dist/combobox/index.js +30 -30
  32. package/dist/dialog/dialog-actions.js +11 -10
  33. package/dist/dialog/dialog.js +18 -18
  34. package/dist/dropdown-menu/item.component.js +24 -24
  35. package/dist/field/field-group.component.js +13 -13
  36. package/dist/field/field.component.js +31 -31
  37. package/dist/fieldset/fieldset.component.js +27 -27
  38. package/dist/grid/grid.component.js +31 -31
  39. package/dist/index.d.ts +1 -0
  40. package/dist/index.js +1 -0
  41. package/dist/index.js.map +1 -1
  42. package/dist/layout/layout.component.js +1 -0
  43. package/dist/layout/navbar-menu-item.component.js +1 -0
  44. package/dist/layout/sidebar-menu-item.component.js +1 -0
  45. package/dist/log-output/log-output.component.js +1 -1
  46. package/dist/meta/index.js +6 -0
  47. package/dist/meta/index.js.map +1 -1
  48. package/dist/meta/public-css-variables.test.d.ts +1 -0
  49. package/dist/meta/public-css-variables.test.js +244 -0
  50. package/dist/meta.json +110 -5
  51. package/dist/number-input/index.js +18 -17
  52. package/dist/option-card/option-card.component.js +27 -27
  53. package/dist/panel/panel-group.component.js +10 -7
  54. package/dist/panel/panel.component.js +3 -3
  55. package/dist/progress/index.js +15 -15
  56. package/dist/quantic-components.js +709 -454
  57. package/dist/quantic-components.js.map +1 -1
  58. package/dist/quantic-components.min.js +606 -548
  59. package/dist/quantic-components.min.js.map +1 -1
  60. package/dist/register.js.map +1 -1
  61. package/dist/select/index.js +8 -8
  62. package/dist/spinner/index.js +7 -3
  63. package/dist/table/table-cell.component.js +2 -2
  64. package/dist/table/table-head.component.js +1 -1
  65. package/dist/table/table.component.js +16 -16
  66. package/dist/tag/index.d.ts +1 -0
  67. package/dist/tag/index.js +1 -0
  68. package/dist/tag/tag-group.component.d.ts +13 -0
  69. package/dist/tag/tag-group.component.js +62 -0
  70. package/dist/tag/tag-group.stories.d.ts +34 -0
  71. package/dist/tag/tag-group.stories.js +65 -0
  72. package/dist/text-input/index.js +10 -10
  73. package/dist/textarea/index.js +10 -10
  74. package/dist/tooltip/tooltip.js +0 -1
  75. package/dist/types/action-group/action-group.component.d.ts +13 -0
  76. package/dist/types/action-group/index.d.ts +1 -0
  77. package/dist/types/action-group/index.stories.d.ts +25 -0
  78. package/dist/types/astro.d.ts +4 -1
  79. package/dist/types/badge/badge-group.component.d.ts +13 -0
  80. package/dist/types/badge/badge-group.stories.d.ts +41 -0
  81. package/dist/types/badge/index.d.ts +1 -0
  82. package/dist/types/button-bar/button-bar-item.d.ts +3 -0
  83. package/dist/types/button-bar/button-bar.d.ts +9 -0
  84. package/dist/types/button-bar/index.utils.d.ts +6 -0
  85. package/dist/types/button-bar/index.utils.test.d.ts +1 -0
  86. package/dist/types/index.d.ts +1 -0
  87. package/dist/types/meta/public-css-variables.test.d.ts +1 -0
  88. package/dist/types/tag/index.d.ts +1 -0
  89. package/dist/types/tag/tag-group.component.d.ts +13 -0
  90. package/dist/types/tag/tag-group.stories.d.ts +34 -0
  91. package/package.json +5 -3
@@ -0,0 +1,13 @@
1
+ import { QuanticElement } from '../shared/quantic-element';
2
+ import type { ComponentMeta } from '../shared/meta.types';
3
+ export declare class BadgeGroup extends QuanticElement {
4
+ static meta: ComponentMeta;
5
+ ariaLabel: string | null;
6
+ static styles: import("lit").CSSResult;
7
+ render(): import("lit").TemplateResult<1>;
8
+ }
9
+ declare global {
10
+ interface HTMLElementTagNameMap {
11
+ 'quantic-badge-group': BadgeGroup;
12
+ }
13
+ }
@@ -0,0 +1,62 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { css, html } from 'lit';
8
+ import { QuanticElement, quanticElement } from '../shared/quantic-element';
9
+ import { prop } from '../shared/component-meta.decorators';
10
+ let BadgeGroup = class BadgeGroup extends QuanticElement {
11
+ constructor() {
12
+ super(...arguments);
13
+ this.ariaLabel = null;
14
+ }
15
+ render() {
16
+ return html `
17
+ <div class="group" role="group" aria-label=${this.ariaLabel ?? 'Badges'}>
18
+ <slot></slot>
19
+ </div>
20
+ `;
21
+ }
22
+ };
23
+ BadgeGroup.meta = {
24
+ tag: 'quantic-badge-group',
25
+ description: 'A run of quantic-badge or quantic-status-badge sharing one accessible name and a consistent gap. ' +
26
+ 'Wraps across lines, and each badge keeps its own size. Gap: --quantic-component-badge-group-gap. ' +
27
+ 'Use quantic-tag-group for tags.',
28
+ category: 'display',
29
+ slots: {
30
+ '': {
31
+ description: 'quantic-badge or quantic-status-badge elements.',
32
+ },
33
+ },
34
+ subComponents: ['quantic-badge', 'quantic-status-badge'],
35
+ relatedTo: ['quantic-badge', 'quantic-tag-group'],
36
+ };
37
+ BadgeGroup.styles = css `
38
+ :host {
39
+ display: block;
40
+ }
41
+
42
+ .group {
43
+ display: flex;
44
+ flex-wrap: wrap;
45
+ align-items: center;
46
+ gap: var(
47
+ --quantic-component-badge-group-gap,
48
+ var(--quantic-spacing-1)
49
+ );
50
+ }
51
+ `;
52
+ __decorate([
53
+ prop({
54
+ type: 'string',
55
+ attribute: 'aria-label',
56
+ description: 'Accessible name for the group.',
57
+ })
58
+ ], BadgeGroup.prototype, "ariaLabel", void 0);
59
+ BadgeGroup = __decorate([
60
+ quanticElement('quantic-badge-group')
61
+ ], BadgeGroup);
62
+ export { BadgeGroup };
@@ -0,0 +1,41 @@
1
+ import { BadgeColor, BadgeSize } from './index.constants';
2
+ interface Args {
3
+ label: string | undefined;
4
+ size: BadgeSize;
5
+ color: BadgeColor;
6
+ badges: string[];
7
+ }
8
+ declare const _default: {
9
+ title: string;
10
+ component: string;
11
+ tags: string[];
12
+ argTypes: {
13
+ label: {
14
+ control: string;
15
+ description: string;
16
+ };
17
+ size: {
18
+ control: {
19
+ type: string;
20
+ };
21
+ options: ("xs" | "sm" | "md" | "lg")[];
22
+ description: string;
23
+ };
24
+ color: {
25
+ control: {
26
+ type: string;
27
+ };
28
+ options: ("success" | "error" | "warning" | "gray" | "brand" | "gray-blue" | "blue-light" | "blue" | "indigo" | "purple" | "pink" | "orange")[];
29
+ description: string;
30
+ };
31
+ badges: {
32
+ control: string;
33
+ description: string;
34
+ };
35
+ };
36
+ };
37
+ export default _default;
38
+ export declare const Default: import("../shared/story").StoryObject<Args>;
39
+ export declare const WithAccessibleName: import("../shared/story").StoryObject<Args>;
40
+ export declare const Wrapping: import("../shared/story").StoryObject<Args>;
41
+ export declare const StatusBadges: import("../shared/story").StoryObject<object>;
@@ -0,0 +1,62 @@
1
+ import { story } from '../shared/story';
2
+ import { BadgeColor, BadgeSize } from './index.constants';
3
+ export default {
4
+ title: 'Components/Display/Badge/BadgeGroup',
5
+ component: 'quantic-badge-group',
6
+ tags: ['autodocs'],
7
+ argTypes: {
8
+ label: {
9
+ control: 'text',
10
+ description: 'Accessible name for the group. Defaults to "Badges".',
11
+ },
12
+ size: {
13
+ control: { type: 'select' },
14
+ options: Object.values(BadgeSize),
15
+ description: 'Size set on each badge. The group does not own sizing.',
16
+ },
17
+ color: {
18
+ control: { type: 'select' },
19
+ options: Object.values(BadgeColor),
20
+ description: 'Color set on each badge',
21
+ },
22
+ badges: {
23
+ control: 'object',
24
+ description: 'Badge labels',
25
+ },
26
+ },
27
+ };
28
+ const base = story({
29
+ args: {
30
+ label: undefined,
31
+ size: BadgeSize.Small,
32
+ color: BadgeColor.Gray,
33
+ badges: ['Backgrounds', 'Email signatures', 'Headers'],
34
+ },
35
+ }).render(({ label, size, color, badges }) => {
36
+ const labelAttr = label === undefined ? '' : `aria-label="${label}"`;
37
+ const items = badges
38
+ .map((badge) => `<quantic-badge color="${color}" size="${size}">${badge}</quantic-badge>`)
39
+ .join('');
40
+ return `<quantic-badge-group ${labelAttr}>${items}</quantic-badge-group>`;
41
+ });
42
+ export const Default = base;
43
+ export const WithAccessibleName = base.override({ label: 'Asset types' });
44
+ // No gap, axis or wrap props on purpose: the rhythm is a decision, not a knob.
45
+ export const Wrapping = base.override({
46
+ badges: [
47
+ 'Backgrounds',
48
+ 'Email signatures',
49
+ 'Headers',
50
+ 'Social graphics',
51
+ 'Slide templates',
52
+ 'Press kits',
53
+ 'Advisory cards',
54
+ ],
55
+ });
56
+ export const StatusBadges = story().render(() => `
57
+ <quantic-badge-group aria-label="Service status">
58
+ <quantic-status-badge color="success" size="sm">Running</quantic-status-badge>
59
+ <quantic-status-badge color="warning" size="sm">Degraded</quantic-status-badge>
60
+ <quantic-status-badge color="error" size="sm">Offline</quantic-status-badge>
61
+ </quantic-badge-group>
62
+ `);
@@ -1,3 +1,4 @@
1
1
  export * from './badge.component';
2
2
  export * from './status-badge.component';
3
+ export * from './badge-group.component';
3
4
  export { BadgeSize, BadgeColor } from './index.constants';
@@ -1,3 +1,4 @@
1
1
  export * from './badge.component';
2
2
  export * from './status-badge.component';
3
+ export * from './badge-group.component';
3
4
  export { BadgeSize, BadgeColor } from './index.constants';
@@ -4,6 +4,9 @@ import type { ComponentMeta } from '../shared/meta.types';
4
4
  export declare class ButtonBarItem extends QuanticElement {
5
5
  static meta: ComponentMeta;
6
6
  size?: ButtonBarSize;
7
+ tabbable: boolean;
8
+ private innerButton?;
9
+ focus(options?: FocusOptions): void;
7
10
  disabled: boolean;
8
11
  active: boolean;
9
12
  static styles: import("lit").CSSResult;
@@ -5,6 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { css, html } from 'lit';
8
+ import { query, state } from 'lit/decorators.js';
8
9
  import { consume } from '@lit/context';
9
10
  import { classMap } from 'lit/directives/class-map.js';
10
11
  import { sizeContext } from './index.context';
@@ -13,9 +14,13 @@ import { prop } from '../shared/component-meta.decorators';
13
14
  let ButtonBarItem = class ButtonBarItem extends QuanticElement {
14
15
  constructor() {
15
16
  super(...arguments);
17
+ this.tabbable = true;
16
18
  this.disabled = false;
17
19
  this.active = false;
18
20
  }
21
+ focus(options) {
22
+ this.innerButton?.focus(options);
23
+ }
19
24
  render() {
20
25
  const classes = classMap({
21
26
  main: true,
@@ -26,7 +31,7 @@ let ButtonBarItem = class ButtonBarItem extends QuanticElement {
26
31
  <button
27
32
  type="button"
28
33
  class=${classes}
29
- tabindex=${this.disabled ? -1 : 0}
34
+ tabindex=${this.disabled || !this.tabbable ? -1 : 0}
30
35
  ?disabled=${this.disabled}
31
36
  aria-pressed=${this.active ? 'true' : 'false'}
32
37
  >
@@ -169,6 +174,12 @@ ButtonBarItem.styles = css `
169
174
  __decorate([
170
175
  consume({ context: sizeContext, subscribe: true })
171
176
  ], ButtonBarItem.prototype, "size", void 0);
177
+ __decorate([
178
+ state()
179
+ ], ButtonBarItem.prototype, "tabbable", void 0);
180
+ __decorate([
181
+ query('button')
182
+ ], ButtonBarItem.prototype, "innerButton", void 0);
172
183
  __decorate([
173
184
  prop({
174
185
  type: 'boolean',
@@ -5,6 +5,15 @@ export declare class ButtonBar extends QuanticElement {
5
5
  static meta: ComponentMeta;
6
6
  size: ButtonBarSize;
7
7
  ariaLabel: string | null;
8
+ private disabledObserver?;
9
+ private hasSynced;
10
+ connectedCallback(): void;
11
+ disconnectedCallback(): void;
12
+ private get items();
13
+ private setFocusStop;
14
+ private syncFocusStop;
15
+ private handleFocusIn;
16
+ private handleKeydown;
8
17
  static styles: import("lit").CSSResult;
9
18
  protected defaultLabel: string;
10
19
  render(): import("lit").TemplateResult<1>;
@@ -10,21 +10,71 @@ import { ButtonBarSize } from './index.constants';
10
10
  import { sizeContext } from './index.context';
11
11
  import { quanticElement, QuanticElement } from '../shared/quantic-element';
12
12
  import { prop } from '../shared/component-meta.decorators';
13
+ import { nextFocusIndex, resolveFocusStop } from './index.utils';
14
+ const ITEM_TAGS = 'quantic-button-bar-item, quantic-button-group-item';
13
15
  let ButtonBar = class ButtonBar extends QuanticElement {
14
16
  constructor() {
15
17
  super(...arguments);
16
18
  this.size = ButtonBarSize.Medium;
17
19
  this.ariaLabel = null;
20
+ this.hasSynced = false;
18
21
  this.defaultLabel = 'Button bar';
19
22
  }
23
+ connectedCallback() {
24
+ super.connectedCallback();
25
+ this.disabledObserver = new MutationObserver(() => this.syncFocusStop());
26
+ this.disabledObserver.observe(this, {
27
+ attributeFilter: ['disabled'],
28
+ subtree: true,
29
+ });
30
+ }
31
+ disconnectedCallback() {
32
+ super.disconnectedCallback();
33
+ this.disabledObserver?.disconnect();
34
+ this.disabledObserver = undefined;
35
+ }
36
+ get items() {
37
+ return [...this.querySelectorAll(ITEM_TAGS)].filter((item) => item.parentElement === this && !item.disabled);
38
+ }
39
+ setFocusStop(items, index) {
40
+ items.forEach((item, position) => {
41
+ item.tabbable = position === index;
42
+ });
43
+ }
44
+ syncFocusStop() {
45
+ const items = this.items;
46
+ const stop = resolveFocusStop(items, this.hasSynced);
47
+ if (stop === null)
48
+ return;
49
+ this.hasSynced = true;
50
+ this.setFocusStop(items, stop);
51
+ }
52
+ handleFocusIn(event) {
53
+ const items = this.items;
54
+ const focused = items.findIndex((item) => item.contains(event.target));
55
+ if (focused !== -1)
56
+ this.setFocusStop(items, focused);
57
+ }
58
+ handleKeydown(event) {
59
+ const items = this.items;
60
+ const current = items.findIndex((item) => item.contains(event.target));
61
+ const next = nextFocusIndex(event.key, current, items.length);
62
+ if (next === null)
63
+ return;
64
+ event.preventDefault();
65
+ this.setFocusStop(items, next);
66
+ items[next].focus();
67
+ }
20
68
  render() {
21
69
  return html `
22
70
  <div
23
71
  class="container"
24
72
  role="toolbar"
25
- aria-label=${this.ariaLabel || this.defaultLabel}
73
+ aria-label=${this.ariaLabel ?? this.defaultLabel}
74
+ @keydown=${this.handleKeydown}
75
+ @focusin=${this.handleFocusIn}
26
76
  >
27
- <slot></slot>
77
+ <slot @slotchange=${() => this.syncFocusStop()}></slot>
28
78
  </div>
29
79
  `;
30
80
  }
@@ -34,6 +84,7 @@ ButtonBar.meta = {
34
84
  description: 'Toolbar of related buttons joined into one cohesive control, with shared sizing. ' +
35
85
  'Use for switching between views or modes, and for a compact run of icon actions. ' +
36
86
  'Items carry aria-pressed via active, so a set can behave as exclusive options or as independent toggles. ' +
87
+ 'Focus follows the toolbar pattern: one tab stop, arrow keys move between items, Home and End jump to the ends. ' +
37
88
  'Prefer quantic-button for a standalone action, and quantic-tabs when each segment reveals a panel.',
38
89
  category: 'action',
39
90
  slots: { '': { description: 'One or more quantic-button-bar-item elements.' } },
@@ -1,14 +1,14 @@
1
1
  import { story } from '../shared/story';
2
2
  import { ButtonBarSize } from './index.constants';
3
3
  export default {
4
- title: 'Components/Actions/Button Group',
4
+ title: 'Components/Actions/Button Bar',
5
5
  component: 'quantic-button-bar',
6
6
  tags: ['autodocs'],
7
7
  argTypes: {
8
8
  size: {
9
9
  control: { type: 'select' },
10
10
  options: Object.values(ButtonBarSize),
11
- description: 'The size of the button group',
11
+ description: 'The size of the button bar',
12
12
  },
13
13
  items: {
14
14
  control: 'object',
@@ -0,0 +1,6 @@
1
+ export interface FocusStopCandidate {
2
+ tabbable: boolean;
3
+ active: boolean;
4
+ }
5
+ export declare function resolveFocusStop(items: FocusStopCandidate[], hasSynced: boolean): number | null;
6
+ export declare function nextFocusIndex(key: string, current: number, count: number): number | null;
@@ -0,0 +1,31 @@
1
+ const KEY_STEPS = {
2
+ ArrowRight: 1,
3
+ ArrowDown: 1,
4
+ ArrowLeft: -1,
5
+ ArrowUp: -1,
6
+ Home: 'first',
7
+ End: 'last',
8
+ };
9
+ export function resolveFocusStop(items, hasSynced) {
10
+ if (!items.length)
11
+ return null;
12
+ if (hasSynced) {
13
+ const tabbable = items.findIndex((item) => item.tabbable);
14
+ if (tabbable !== -1)
15
+ return tabbable;
16
+ }
17
+ const active = items.findIndex((item) => item.active);
18
+ return active === -1 ? 0 : active;
19
+ }
20
+ export function nextFocusIndex(key, current, count) {
21
+ const step = KEY_STEPS[key];
22
+ if (step === undefined)
23
+ return null;
24
+ if (count < 2 || current < 0 || current >= count)
25
+ return null;
26
+ if (step === 'first')
27
+ return 0;
28
+ if (step === 'last')
29
+ return count - 1;
30
+ return (current + step + count) % count;
31
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,53 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { nextFocusIndex, resolveFocusStop } from './index.utils';
3
+ const item = (tabbable, active = false) => ({ tabbable, active });
4
+ describe('resolveFocusStop', () => {
5
+ it('starts on the active item', () => {
6
+ expect(resolveFocusStop([item(true), item(true, true), item(true)], false)).toBe(1);
7
+ });
8
+ it('starts on the first item when none is active', () => {
9
+ expect(resolveFocusStop([item(true), item(true)], false)).toBe(0);
10
+ });
11
+ it('keeps the existing stop once synced, so a resync does not move focus', () => {
12
+ expect(resolveFocusStop([item(false), item(true), item(false, true)], true)).toBe(1);
13
+ });
14
+ it('rehomes the stop when the item holding it is gone', () => {
15
+ expect(resolveFocusStop([item(false), item(false, true)], true)).toBe(1);
16
+ expect(resolveFocusStop([item(false), item(false)], true)).toBe(0);
17
+ });
18
+ it('has nothing to do without items', () => {
19
+ expect(resolveFocusStop([], false)).toBeNull();
20
+ expect(resolveFocusStop([], true)).toBeNull();
21
+ });
22
+ });
23
+ describe('nextFocusIndex', () => {
24
+ it('moves forward and back', () => {
25
+ expect(nextFocusIndex('ArrowRight', 0, 3)).toBe(1);
26
+ expect(nextFocusIndex('ArrowLeft', 2, 3)).toBe(1);
27
+ });
28
+ it('treats the vertical arrows the same, so a wrapped bar still navigates', () => {
29
+ expect(nextFocusIndex('ArrowDown', 0, 3)).toBe(1);
30
+ expect(nextFocusIndex('ArrowUp', 1, 3)).toBe(0);
31
+ });
32
+ it('wraps at both ends', () => {
33
+ expect(nextFocusIndex('ArrowRight', 2, 3)).toBe(0);
34
+ expect(nextFocusIndex('ArrowLeft', 0, 3)).toBe(2);
35
+ });
36
+ it('jumps to the ends', () => {
37
+ expect(nextFocusIndex('Home', 2, 3)).toBe(0);
38
+ expect(nextFocusIndex('End', 0, 3)).toBe(2);
39
+ });
40
+ it('ignores keys it does not own, so Tab and Enter still behave natively', () => {
41
+ expect(nextFocusIndex('Tab', 0, 3)).toBeNull();
42
+ expect(nextFocusIndex('Enter', 0, 3)).toBeNull();
43
+ expect(nextFocusIndex(' ', 0, 3)).toBeNull();
44
+ });
45
+ it('does nothing without at least two items', () => {
46
+ expect(nextFocusIndex('ArrowRight', 0, 1)).toBeNull();
47
+ expect(nextFocusIndex('ArrowRight', 0, 0)).toBeNull();
48
+ });
49
+ it('does nothing when the event came from outside the items', () => {
50
+ expect(nextFocusIndex('ArrowRight', -1, 3)).toBeNull();
51
+ expect(nextFocusIndex('ArrowRight', 3, 3)).toBeNull();
52
+ });
53
+ });
@@ -21,8 +21,7 @@ let ButtonGroup = class ButtonGroup extends ButtonBar {
21
21
  ButtonGroup.meta = {
22
22
  ...ButtonBar.meta,
23
23
  tag: 'quantic-button-group',
24
- description: 'Deprecated alias of quantic-button-bar. This element never grouped buttons: ' +
25
- 'it joins borders and gives its items a pressed state. Use quantic-button-bar.',
24
+ description: 'Deprecated alias of quantic-button-bar. Use quantic-button-bar.',
26
25
  deprecated: {
27
26
  use: 'quantic-button-bar',
28
27
  reason: 'The name describes a row of buttons, which this is not. Use quantic-action-group for that.',
@@ -92,77 +92,77 @@ CapacityBar.styles = css `
92
92
 
93
93
  .label {
94
94
  color: var(--quantic-text-secondary);
95
- font-size: var(--quantic-component-capacity-bar-label-font-size);
96
- line-height: var(--quantic-component-capacity-bar-label-line-height);
95
+ font-size: var(--quantic-component-capacity-bar-label-font-size, var(--quantic-internal-capacity-bar-label-font-size));
96
+ line-height: var(--quantic-component-capacity-bar-label-line-height, var(--quantic-internal-capacity-bar-label-line-height));
97
97
  white-space: nowrap;
98
98
  }
99
99
 
100
100
  .bar {
101
101
  display: flex;
102
102
  flex-wrap: nowrap;
103
- gap: var(--quantic-component-capacity-bar-gap, 3px);
103
+ gap: var(--quantic-component-capacity-bar-gap, var(--quantic-internal-capacity-bar-gap, 3px));
104
104
  }
105
105
 
106
106
  .size--xs {
107
- --quantic-component-capacity-bar-gap: 2px;
108
- --quantic-component-capacity-bar-segment-radius: 2px;
109
- --quantic-component-capacity-bar-segment-width: 3px;
110
- --quantic-component-capacity-bar-segment-height: var(--quantic-spacing-5);
111
- --quantic-component-capacity-bar-label-font-size: var(
107
+ --quantic-internal-capacity-bar-gap: 2px;
108
+ --quantic-internal-capacity-bar-segment-radius: 2px;
109
+ --quantic-internal-capacity-bar-segment-width: 3px;
110
+ --quantic-internal-capacity-bar-segment-height: var(--quantic-spacing-5);
111
+ --quantic-internal-capacity-bar-label-font-size: var(
112
112
  --quantic-font-size-body-xs
113
113
  );
114
- --quantic-component-capacity-bar-label-line-height: var(
114
+ --quantic-internal-capacity-bar-label-line-height: var(
115
115
  --quantic-line-height-body-xs
116
116
  );
117
117
  }
118
118
 
119
119
  .size--sm {
120
- --quantic-component-capacity-bar-gap: 2px;
121
- --quantic-component-capacity-bar-segment-radius: 2px;
122
- --quantic-component-capacity-bar-segment-width: var(--quantic-spacing-1);
123
- --quantic-component-capacity-bar-segment-height: var(--quantic-spacing-6);
124
- --quantic-component-capacity-bar-label-font-size: var(
120
+ --quantic-internal-capacity-bar-gap: 2px;
121
+ --quantic-internal-capacity-bar-segment-radius: 2px;
122
+ --quantic-internal-capacity-bar-segment-width: var(--quantic-spacing-1);
123
+ --quantic-internal-capacity-bar-segment-height: var(--quantic-spacing-6);
124
+ --quantic-internal-capacity-bar-label-font-size: var(
125
125
  --quantic-font-size-body-xs
126
126
  );
127
- --quantic-component-capacity-bar-label-line-height: var(
127
+ --quantic-internal-capacity-bar-label-line-height: var(
128
128
  --quantic-line-height-body-xs
129
129
  );
130
130
  }
131
131
 
132
132
  .size--md {
133
- --quantic-component-capacity-bar-gap: 2px;
134
- --quantic-component-capacity-bar-segment-radius: 3px;
135
- --quantic-component-capacity-bar-segment-width: var(
133
+ --quantic-internal-capacity-bar-gap: 2px;
134
+ --quantic-internal-capacity-bar-segment-radius: 3px;
135
+ --quantic-internal-capacity-bar-segment-width: var(
136
136
  --quantic-spacing-1-5
137
137
  );
138
- --quantic-component-capacity-bar-segment-height: var(--quantic-spacing-8);
139
- --quantic-component-capacity-bar-label-font-size: var(
138
+ --quantic-internal-capacity-bar-segment-height: var(--quantic-spacing-8);
139
+ --quantic-internal-capacity-bar-label-font-size: var(
140
140
  --quantic-font-size-body-sm
141
141
  );
142
- --quantic-component-capacity-bar-label-line-height: var(
142
+ --quantic-internal-capacity-bar-label-line-height: var(
143
143
  --quantic-line-height-body-sm
144
144
  );
145
145
  }
146
146
 
147
147
  .size--lg {
148
- --quantic-component-capacity-bar-gap: 3px;
149
- --quantic-component-capacity-bar-segment-radius: 4px;
150
- --quantic-component-capacity-bar-segment-width: var(--quantic-spacing-2);
151
- --quantic-component-capacity-bar-segment-height: var(
148
+ --quantic-internal-capacity-bar-gap: 3px;
149
+ --quantic-internal-capacity-bar-segment-radius: 4px;
150
+ --quantic-internal-capacity-bar-segment-width: var(--quantic-spacing-2);
151
+ --quantic-internal-capacity-bar-segment-height: var(
152
152
  --quantic-spacing-12
153
153
  );
154
- --quantic-component-capacity-bar-label-font-size: var(
154
+ --quantic-internal-capacity-bar-label-font-size: var(
155
155
  --quantic-font-size-body-md
156
156
  );
157
- --quantic-component-capacity-bar-label-line-height: var(
157
+ --quantic-internal-capacity-bar-label-line-height: var(
158
158
  --quantic-line-height-body-md
159
159
  );
160
160
  }
161
161
 
162
162
  .segment {
163
- width: var(--quantic-component-capacity-bar-segment-width, 6px);
164
- height: var(--quantic-component-capacity-bar-segment-height, 6px);
165
- border-radius: var(--quantic-component-capacity-bar-segment-radius, 4px);
163
+ width: var(--quantic-component-capacity-bar-segment-width, var(--quantic-internal-capacity-bar-segment-width, 6px));
164
+ height: var(--quantic-component-capacity-bar-segment-height, var(--quantic-internal-capacity-bar-segment-height, 6px));
165
+ border-radius: var(--quantic-component-capacity-bar-segment-radius, var(--quantic-internal-capacity-bar-segment-radius, 4px));
166
166
  }
167
167
 
168
168
  .segment--empty {