Skip to content

Commit 5619cb2

Browse files
authored
Merge pull request #241 from qualcomm/olaf/feat/split-button
feat: split button
2 parents d89f2a5 + 52c2c9d commit 5619cb2

59 files changed

Lines changed: 1395 additions & 430 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,5 +108,5 @@
108108
"prettier": "3.8.3",
109109
"typescript": "catalog:"
110110
},
111-
"packageManager": "pnpm@11.3.0+sha512.2c403d6594527287672b1f7056343a1f7c3634036a67ffabfcc2b3d7595d843768f8787148d1b57cf7956c90606bbd192857c363af19e96d2d0ec9ec5741d215"
111+
"packageManager": "pnpm@11.5.1+sha512.93f7b57422ea7068257235b4c16eb60762eb68e1dc23723199cc739043ea9be2c4143274a399d8c6defa2b1176226d9ca1c4b63482d6200c1a8fbaa78c1d1485"
112112
}

packages/common/qds-core/CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
# @qualcomm-ui/qds-core Changelog
22

3+
## 1.29.0
4+
5+
Jun 4th, 2026
6+
7+
### Features
8+
9+
- [tag]: support controlled selected state ([f2b0d0c](https://github.com/qualcomm/qualcomm-ui/commit/f2b0d0c))
10+
- [menu]: add split button ([527d33e](https://github.com/qualcomm/qualcomm-ui/commit/527d33e))
11+
- [tag]: add aria-pressed to selectable tag ([81a24a3](https://github.com/qualcomm/qualcomm-ui/commit/81a24a3))
12+
13+
### Code Refactoring
14+
15+
- [button]: consolidate button-group prop resolution ([3922878](https://github.com/qualcomm/qualcomm-ui/commit/3922878))
16+
17+
### Bug Fixes
18+
19+
- [tag]: correct icon sizing for nested icons ([d1618e5](https://github.com/qualcomm/qualcomm-ui/commit/d1618e5))
20+
- [menu]: keep variant background on menu button triggers ([6892122](https://github.com/qualcomm/qualcomm-ui/commit/6892122))
21+
322
## 1.28.4
423

524
Jun 3rd, 2026

packages/common/qds-core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@qualcomm-ui/qds-core",
3-
"version": "1.28.4",
3+
"version": "1.29.0",
44
"description": "qds core components",
55
"author": "Ryan Bower",
66
"license": "BSD-3-Clause-Clear",
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
2+
// SPDX-License-Identifier: BSD-3-Clause-Clear
3+
4+
import type {BooleanDataAttr} from "@qualcomm-ui/utils/attributes"
5+
6+
import type {
7+
QdsButtonDensity,
8+
QdsButtonEmphasis,
9+
QdsButtonSize,
10+
QdsButtonVariant,
11+
} from "./button.types"
12+
13+
/**
14+
* Props and bindings shared between button group and split button.
15+
*/
16+
17+
export interface QdsButtonGroupCommonProps {
18+
/**
19+
* {@link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-label aria-label}
20+
* attribute.
21+
*/
22+
["aria-label"]?: string
23+
24+
/**
25+
* {@link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-labelledby aria-labelledby}
26+
* attribute.
27+
*/
28+
["aria-labelledby"]?: string
29+
30+
/**
31+
* The density of the buttons. Governs padding and height.
32+
*
33+
* @default 'default'
34+
*/
35+
density?: QdsButtonDensity
36+
37+
/**
38+
* Disables every button in the group.
39+
*
40+
* @default false
41+
*/
42+
disabled?: boolean | undefined
43+
44+
/**
45+
* The emphasis of the buttons in the group.
46+
*/
47+
emphasis?: QdsButtonEmphasis
48+
49+
/**
50+
* The size of the buttons in the group.
51+
*
52+
* @default 'md'
53+
*/
54+
size?: QdsButtonSize
55+
56+
/**
57+
* The variant of the buttons in the group.
58+
*/
59+
variant?: QdsButtonVariant
60+
}
61+
62+
export interface QdsButtonGroupCommonBindings {
63+
"aria-label"?: string
64+
"aria-labelledby"?: string
65+
"data-density": QdsButtonDensity
66+
"data-disabled": BooleanDataAttr
67+
"data-emphasis"?: QdsButtonEmphasis
68+
"data-size": QdsButtonSize
69+
"data-variant"?: QdsButtonVariant
70+
role?: "group"
71+
}

packages/common/qds-core/src/button/button-group.api.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,35 @@ import type {
1111
QdsButtonGroupBindings,
1212
} from "./button-group.types"
1313
import {buttonClasses} from "./button.classes"
14+
import type {QdsButtonApiProps} from "./button.types"
15+
16+
export type ResolvableButtonGroupProps = Pick<
17+
QdsButtonGroupApiProps,
18+
keyof QdsButtonGroupApiProps & keyof QdsButtonApiProps
19+
>
20+
21+
/**
22+
* Merges button-group context values with a button's own props.
23+
*
24+
* `density`, `disabled`, and `size` are non-overridable (group wins).
25+
* `emphasis` and `variant` are overridable per-button (button wins).
26+
*/
27+
export function resolveButtonPropsWithGroup<
28+
T extends ResolvableButtonGroupProps,
29+
>(group: ResolvableButtonGroupProps | undefined, base: T): T {
30+
if (!group) {
31+
return base
32+
}
33+
const {density, disabled, emphasis, size, variant} = group
34+
return {
35+
...base,
36+
density: density ?? base.density,
37+
disabled: disabled ?? base.disabled,
38+
emphasis: base.emphasis ?? emphasis,
39+
size: size ?? base.size,
40+
variant: base.variant ?? variant,
41+
}
42+
}
1443

1544
const parts = buttonGroupAnatomy.parts
1645

packages/common/qds-core/src/button/button-group.types.ts

Lines changed: 7 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2,52 +2,20 @@
22
// SPDX-License-Identifier: BSD-3-Clause-Clear
33

44
import type {AnatomyPart, AnatomyPartName} from "@qualcomm-ui/utils/anatomy"
5-
import type {BooleanDataAttr} from "@qualcomm-ui/utils/attributes"
65

6+
import type {
7+
QdsButtonGroupCommonBindings,
8+
QdsButtonGroupCommonProps,
9+
} from "./button-group-shared.types"
710
import type {buttonGroupAnatomy} from "./button-group.anatomy"
811
import type {buttonClasses} from "./button.classes"
9-
import type {
10-
QdsButtonDensity,
11-
QdsButtonEmphasis,
12-
QdsButtonSize,
13-
QdsButtonVariant,
14-
} from "./button.types"
1512

1613
/**
1714
* The button group layouts
1815
*/
1916
export type QdsButtonGroupLayout = "hug" | "start" | "end" | "fill"
2017

21-
export interface QdsButtonGroupApiProps {
22-
/**
23-
* Accessible name for the button group.
24-
*/
25-
["aria-label"]?: string
26-
27-
/**
28-
* Id(s) of element(s) that label the button group.
29-
*/
30-
["aria-labelledby"]?: string
31-
32-
/**
33-
* The density of the button. Governs padding and height.
34-
*
35-
* @default 'default'
36-
*/
37-
density?: QdsButtonDensity
38-
39-
/**
40-
* Disables all buttons within the group.
41-
*
42-
* @default false
43-
*/
44-
disabled?: boolean | undefined
45-
46-
/**
47-
* The emphasis of the buttons in the group.
48-
*/
49-
emphasis?: QdsButtonEmphasis
50-
18+
export interface QdsButtonGroupApiProps extends QdsButtonGroupCommonProps {
5119
/**
5220
* The layout used to display the button group.
5321
* - `hug`: Content-sized; width matches the buttons only (default).
@@ -58,31 +26,13 @@ export interface QdsButtonGroupApiProps {
5826
* @default 'hug'
5927
*/
6028
layout?: QdsButtonGroupLayout
61-
62-
/**
63-
* The size of the buttons in the group.
64-
*
65-
* @default 'md'
66-
*/
67-
size?: QdsButtonSize
68-
69-
/**
70-
* The variant of the buttons in the group.
71-
*/
72-
variant?: QdsButtonVariant
7329
}
7430

7531
type PartName = AnatomyPartName<typeof buttonGroupAnatomy>
7632
interface Part<P extends PartName> extends AnatomyPart<"buttonGroup", P> {}
7733

78-
export interface QdsButtonGroupBindings extends Part<"root"> {
79-
"aria-label"?: string
80-
"aria-labelledby"?: string
34+
export interface QdsButtonGroupBindings
35+
extends Part<"root">, QdsButtonGroupCommonBindings {
8136
className: (typeof buttonClasses)["group"]
82-
"data-disabled": BooleanDataAttr
83-
"data-emphasis"?: QdsButtonEmphasis
8437
"data-layout": QdsButtonGroupLayout
85-
"data-size"?: QdsButtonSize
86-
"data-variant"?: QdsButtonVariant
87-
role?: "group"
8838
}

packages/common/qds-core/src/button/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export type * from "./button-group-shared.types"
12
export * from "./button-group.anatomy"
23
export * from "./button-group.api"
34
export type * from "./button-group.types"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
export * from "./menu.anatomy"
22
export * from "./menu-item.classes"
3+
export * from "./menu-split-button.anatomy"
4+
export * from "./menu-split-button.api"
5+
export type * from "./menu-split-button.types"
36
export * from "./menu.api"
47
export * from "./menu.classes"
58
export type * from "./menu.types"
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
2+
// SPDX-License-Identifier: BSD-3-Clause-Clear
3+
4+
import {type Anatomy, createAnatomy} from "@qualcomm-ui/utils/anatomy"
5+
6+
const parts = ["root"] as const
7+
8+
export const splitButtonAnatomy: Anatomy<
9+
"splitButton",
10+
(typeof parts)[number]
11+
> = createAnatomy("splitButton").parts(...parts)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
2+
// SPDX-License-Identifier: BSD-3-Clause-Clear
3+
4+
import {booleanDataAttr} from "@qualcomm-ui/utils/attributes"
5+
import type {Explicit} from "@qualcomm-ui/utils/guard"
6+
import type {PropNormalizer} from "@qualcomm-ui/utils/machine"
7+
8+
import {splitButtonAnatomy} from "./menu-split-button.anatomy"
9+
import type {
10+
QdsSplitButtonApiProps,
11+
QdsSplitButtonBindings,
12+
} from "./menu-split-button.types"
13+
import {menuClasses} from "./menu.classes"
14+
15+
const parts = splitButtonAnatomy.parts
16+
17+
export function getQdsSplitButtonBindings(
18+
{
19+
"aria-label": ariaLabel,
20+
"aria-labelledby": ariaLabelledby,
21+
density,
22+
disabled,
23+
emphasis,
24+
size,
25+
variant,
26+
}: Explicit<QdsSplitButtonApiProps>,
27+
normalize: PropNormalizer,
28+
): QdsSplitButtonBindings {
29+
const hasAriaLabel = !!(ariaLabel || ariaLabelledby)
30+
31+
return normalize.element({
32+
...parts.root,
33+
"aria-label": ariaLabel || undefined,
34+
"aria-labelledby": ariaLabelledby || undefined,
35+
className: menuClasses.splitButton,
36+
"data-density": density || "default",
37+
"data-disabled": booleanDataAttr(disabled),
38+
"data-emphasis": emphasis || undefined,
39+
"data-size": size || "md",
40+
"data-variant": variant || undefined,
41+
...(hasAriaLabel && {role: "group"}),
42+
})
43+
}

0 commit comments

Comments
 (0)