@astryxdesign/core 0.7.2-canary.86e8392 → 0.7.2-canary.9da2d0b
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.
- package/dist/Drawer/Drawer.d.ts.map +1 -1
- package/dist/Drawer/Drawer.js +4 -4
- package/dist/Drawer/DrawerHeader.d.ts +2 -1
- package/dist/Drawer/DrawerHeader.d.ts.map +1 -1
- package/dist/Drawer/DrawerHeader.js +8 -7
- package/dist/DropdownMenu/DropdownMenuDivider.d.ts +5 -3
- package/dist/DropdownMenu/DropdownMenuDivider.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuDivider.js +7 -3
- package/dist/TabList/TabMenu.d.ts +2 -2
- package/dist/TabList/TabMenu.d.ts.map +1 -1
- package/dist/TabList/TabMenu.js +6 -3
- package/dist/astryx.css +4 -0
- package/package.json +3 -3
- package/src/Drawer/Drawer.spec.md +8 -6
- package/src/Drawer/Drawer.tsx +7 -6
- package/src/Drawer/DrawerDirection.test.tsx +127 -0
- package/src/Drawer/DrawerHeader.test.tsx +13 -0
- package/src/Drawer/DrawerHeader.tsx +8 -8
- package/src/Drawer/__tests__/DrawerAudit.a11y.chromium.spec.ts +401 -0
- package/src/Drawer/__tests__/DrawerHeaderAudit.a11y.chromium.spec.ts +297 -0
- package/src/DropdownMenu/DropdownMenu.test.tsx +21 -12
- package/src/DropdownMenu/DropdownMenuDivider.doc.mjs +2 -2
- package/src/DropdownMenu/DropdownMenuDivider.tsx +9 -5
- package/src/DropdownMenu/__tests__/Menu.a11y.chromium.spec.ts +145 -0
- package/src/DropdownMenu/__tests__/Menu.a11y.known-failures.ts +26 -0
- package/src/DropdownMenu/__tests__/Menu.a11y.renders.tsx +65 -0
- package/src/DropdownMenu/__tests__/Menu.a11y.states.ts +138 -0
- package/src/DropdownMenu/__tests__/Menu.a11y.test.tsx +136 -0
- package/src/Item/Item.spec.md +226 -0
- package/src/TabList/TabList.test.tsx +67 -0
- package/src/TabList/TabMenu.doc.mjs +4 -3
- package/src/TabList/TabMenu.tsx +7 -4
- package/src/TreeList/TreeList.spec.md +29 -17
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Drawer.d.ts","sourceRoot":"","sources":["../../src/Drawer/Drawer.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AAEH,OAAO,EAAgC,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAEpE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAQ5C,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,WAAW,CAAC;AAe7C,OAAO,KAAK,EAAC,WAAW,EAAe,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"Drawer.d.ts","sourceRoot":"","sources":["../../src/Drawer/Drawer.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AAEH,OAAO,EAAgC,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAEpE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAQ5C,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,WAAW,CAAC;AAe7C,OAAO,KAAK,EAAC,WAAW,EAAe,MAAM,WAAW,CAAC;AAgMzD,MAAM,WAAW,WAAY,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IAC/D,iDAAiD;IACjD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAEnC;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAEhB;;;;;;OAMG;IACH,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAExC;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IAEvB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAExB;;;;;OAKG;IACH,YAAY,CAAC,EAAE;QACb;;;;;;WAMG;QACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;KAC/B,CAAC;IAEF;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;IAExB;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB;;;OAGG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,MAAM,CAAC,EACrB,MAAM,EACN,YAAY,EACZ,IAAY,EACZ,KAAW,EACX,YAAY,EACZ,KAAK,EACL,QAAe,EACf,OAAgB,EAChB,OAAO,EACP,QAAQ,EACR,MAAM,EACN,SAAS,EACT,KAAK,EACL,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,aAAa,EACxB,GAAG,EACH,GAAG,KAAK,EACT,EAAE,WAAW,+BA4Kb;yBA9Le,MAAM"}
|
package/dist/Drawer/Drawer.js
CHANGED
|
@@ -123,11 +123,11 @@ const styles = {
|
|
|
123
123
|
k2ei4v: "xgbv0en",
|
|
124
124
|
kVhnKS: "x1t7ytsu",
|
|
125
125
|
kGJrpR: "x1j92z86",
|
|
126
|
-
k3aq6I: "xumwmo6
|
|
126
|
+
k3aq6I: "xumwmo6 xbw113y",
|
|
127
127
|
$$css: true
|
|
128
128
|
},
|
|
129
129
|
endOpen: {
|
|
130
|
-
k3aq6I: "xbryuvx x1yqmsfc
|
|
130
|
+
k3aq6I: "xbryuvx x1yqmsfc xrxqmjf",
|
|
131
131
|
$$css: true
|
|
132
132
|
},
|
|
133
133
|
start: {
|
|
@@ -136,11 +136,11 @@ const styles = {
|
|
|
136
136
|
ke9TFa: "xw8tdv1",
|
|
137
137
|
k8ry5P: "x18b5jzi",
|
|
138
138
|
kBCPoo: "x1gejf6u",
|
|
139
|
-
k3aq6I: "x5i6ehr
|
|
139
|
+
k3aq6I: "x5i6ehr x1eqdj8u",
|
|
140
140
|
$$css: true
|
|
141
141
|
},
|
|
142
142
|
startOpen: {
|
|
143
|
-
k3aq6I: "xbryuvx x6mt36l
|
|
143
|
+
k3aq6I: "xbryuvx x6mt36l x1r0dqvm",
|
|
144
144
|
$$css: true
|
|
145
145
|
},
|
|
146
146
|
scrim: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file DrawerHeader.tsx
|
|
3
|
-
* @input Uses React, StyleX, LayoutHeader, Button, Icon, Heading, Text, i18n, BaseProps, mergeProps, themeProps
|
|
3
|
+
* @input Uses React, StyleX, LayoutHeader, Button, Icon, Heading, Text, i18n, BaseProps, isRenderable, mergeProps, themeProps
|
|
4
4
|
* @output Exports DrawerHeader component and DrawerHeaderProps
|
|
5
5
|
* @position Drawer header; composed in a Layout header slot inside Drawer, tested by DrawerHeader.test.tsx
|
|
6
6
|
*
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* - /packages/cli/assets/templates/blocks/components/Drawer/ (showcase blocks)
|
|
19
19
|
* - /packages/cli/assets/templates/blocks/components/DrawerHeader/ (showcase blocks)
|
|
20
20
|
* - /apps/storybook/stories/Drawer.stories.tsx (examples and visual coverage)
|
|
21
|
+
* - /apps/storybook/stories/DrawerHeader.stories.tsx (component audit fixture)
|
|
21
22
|
*/
|
|
22
23
|
import type { ReactNode } from 'react';
|
|
23
24
|
import type { BaseProps } from '../BaseProps';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DrawerHeader.d.ts","sourceRoot":"","sources":["../../src/Drawer/DrawerHeader.tsx"],"names":[],"mappings":"AAIA
|
|
1
|
+
{"version":3,"file":"DrawerHeader.d.ts","sourceRoot":"","sources":["../../src/Drawer/DrawerHeader.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAErC,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AA0C5C,MAAM,WAAW,iBAAkB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAClE,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEhC;;;OAGG;IACH,KAAK,EAAE,SAAS,CAAC;IAEjB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IAE5C;;OAEG;IACH,YAAY,CAAC,EAAE,SAAS,CAAC;IAEzB;;;OAGG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IAEvB;;;;OAIG;IACH,0BAA0B,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,KAAK,CAAC;IAExD;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,0BAA0B,EAC1B,UAAU,EACV,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,IAAI,EACR,EAAE,iBAAiB,+BAoFnB;yBAjGe,YAAY"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file DrawerHeader.tsx
|
|
7
|
-
* @input Uses React, StyleX, LayoutHeader, Button, Icon, Heading, Text, i18n, BaseProps, mergeProps, themeProps
|
|
7
|
+
* @input Uses React, StyleX, LayoutHeader, Button, Icon, Heading, Text, i18n, BaseProps, isRenderable, mergeProps, themeProps
|
|
8
8
|
* @output Exports DrawerHeader component and DrawerHeaderProps
|
|
9
9
|
* @position Drawer header; composed in a Layout header slot inside Drawer, tested by DrawerHeader.test.tsx
|
|
10
10
|
*
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* - /packages/cli/assets/templates/blocks/components/Drawer/ (showcase blocks)
|
|
23
23
|
* - /packages/cli/assets/templates/blocks/components/DrawerHeader/ (showcase blocks)
|
|
24
24
|
* - /apps/storybook/stories/Drawer.stories.tsx (examples and visual coverage)
|
|
25
|
+
* - /apps/storybook/stories/DrawerHeader.stories.tsx (component audit fixture)
|
|
25
26
|
*/
|
|
26
27
|
import * as stylex from '@stylexjs/stylex';
|
|
27
28
|
import "../theme/tokens.stylex.js";
|
|
@@ -32,7 +33,7 @@ import { Icon } from "../Icon/index.js";
|
|
|
32
33
|
import { LayoutHeader } from "../Layout/index.js";
|
|
33
34
|
import { Text } from "../Text/index.js";
|
|
34
35
|
import { useTranslator } from "../i18n/index.js";
|
|
35
|
-
import { mergeProps, themeProps } from "../utils/index.js";
|
|
36
|
+
import { isRenderable, mergeProps, themeProps } from "../utils/index.js";
|
|
36
37
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
37
38
|
/**
|
|
38
39
|
* Header for a Drawer: a title, optional subtitle and start/end content, and a
|
|
@@ -63,9 +64,9 @@ export function DrawerHeader({
|
|
|
63
64
|
...rest
|
|
64
65
|
}) {
|
|
65
66
|
const t = useTranslator();
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const
|
|
67
|
+
const hasSubtitle = isRenderable(subtitle);
|
|
68
|
+
const hasStartContent = isRenderable(startContent);
|
|
69
|
+
const hasEndContent = isRenderable(endContent);
|
|
69
70
|
const shouldCompensateEndBlock = endContentEdgeCompensation == null ? onOpenChange != null : endContentEdgeCompensation === 'block' || endContentEdgeCompensation === 'all';
|
|
70
71
|
const shouldCompensateEndInline = endContentEdgeCompensation == null ? onOpenChange != null : endContentEdgeCompensation === 'inline' || endContentEdgeCompensation === 'all';
|
|
71
72
|
return /*#__PURE__*/_jsx(LayoutHeader, {
|
|
@@ -79,7 +80,7 @@ export function DrawerHeader({
|
|
|
79
80
|
...mergeProps(themeProps('drawer-header'), {
|
|
80
81
|
className: "x78zum5 x1cy8zhl x1qughib xjcht0a"
|
|
81
82
|
}),
|
|
82
|
-
children: [
|
|
83
|
+
children: [hasStartContent && /*#__PURE__*/_jsx("div", {
|
|
83
84
|
...mergeProps(themeProps('drawer-header-start-content'), {
|
|
84
85
|
className: "x78zum5 x6s0dn4 x1txdalj x2lah0s"
|
|
85
86
|
}),
|
|
@@ -97,7 +98,7 @@ export function DrawerHeader({
|
|
|
97
98
|
color: "secondary",
|
|
98
99
|
children: subtitle
|
|
99
100
|
})]
|
|
100
|
-
}), (
|
|
101
|
+
}), (hasEndContent || onOpenChange != null) && /*#__PURE__*/_jsxs("div", {
|
|
101
102
|
...mergeProps(themeProps('drawer-header-end-content'), {
|
|
102
103
|
0: {
|
|
103
104
|
className: "x78zum5 x6s0dn4 x1txdalj x2lah0s"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BaseProps } from '../BaseProps';
|
|
2
|
-
export interface DropdownMenuDividerProps extends
|
|
2
|
+
export interface DropdownMenuDividerProps extends Omit<BaseProps<HTMLDivElement>, 'role' | 'aria-orientation'> {
|
|
3
3
|
/** Ref forwarded to the separator element. */
|
|
4
4
|
ref?: React.Ref<HTMLDivElement>;
|
|
5
5
|
}
|
|
@@ -7,7 +7,9 @@ export interface DropdownMenuDividerProps extends Pick<BaseProps, 'xstyle' | 'cl
|
|
|
7
7
|
* A horizontal rule separating groups of menu rows.
|
|
8
8
|
*
|
|
9
9
|
* Renders `role="separator"`, so it is never a stop in the menu's arrow-key
|
|
10
|
-
* order. Equivalent to `{type: 'divider'}` in the `items` data API.
|
|
10
|
+
* order. Equivalent to `{type: 'divider'}` in the `items` data API. Host
|
|
11
|
+
* attributes (`id`, `data-*`, `aria-*`) and DOM handlers reach the separator;
|
|
12
|
+
* its role and orientation stay component-owned.
|
|
11
13
|
*
|
|
12
14
|
* @example
|
|
13
15
|
* ```
|
|
@@ -18,7 +20,7 @@ export interface DropdownMenuDividerProps extends Pick<BaseProps, 'xstyle' | 'cl
|
|
|
18
20
|
* </DropdownMenu>
|
|
19
21
|
* ```
|
|
20
22
|
*/
|
|
21
|
-
export declare function DropdownMenuDivider({ xstyle, className, style, ref, }: DropdownMenuDividerProps): import("react").JSX.Element;
|
|
23
|
+
export declare function DropdownMenuDivider({ xstyle, className, style, ref, ...rest }: DropdownMenuDividerProps): import("react").JSX.Element;
|
|
22
24
|
export declare namespace DropdownMenuDivider {
|
|
23
25
|
var displayName: string;
|
|
24
26
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DropdownMenuDivider.d.ts","sourceRoot":"","sources":["../../src/DropdownMenu/DropdownMenuDivider.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAW5C,MAAM,WAAW,wBAAyB,SAAQ,IAAI,CACpD,SAAS,
|
|
1
|
+
{"version":3,"file":"DropdownMenuDivider.d.ts","sourceRoot":"","sources":["../../src/DropdownMenu/DropdownMenuDivider.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAW5C,MAAM,WAAW,wBAAyB,SAAQ,IAAI,CACpD,SAAS,CAAC,cAAc,CAAC,EACzB,MAAM,GAAG,kBAAkB,CAC5B;IACC,8CAA8C;IAC9C,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,IAAI,EACR,EAAE,wBAAwB,+BAY1B;yBAlBe,mBAAmB"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file DropdownMenuDivider.tsx
|
|
7
|
-
* @input Uses Divider, spacing tokens, themeProps
|
|
7
|
+
* @input Uses Divider, spacing tokens, themeProps; forwards host props to Divider
|
|
8
8
|
* @output Exports DropdownMenuDivider component and DropdownMenuDividerProps
|
|
9
9
|
* @position Sub-component; used inside DropdownMenu
|
|
10
10
|
*
|
|
@@ -39,7 +39,9 @@ const THEME_CLASS_NAME = themeProps('dropdown-menu-divider').className;
|
|
|
39
39
|
* A horizontal rule separating groups of menu rows.
|
|
40
40
|
*
|
|
41
41
|
* Renders `role="separator"`, so it is never a stop in the menu's arrow-key
|
|
42
|
-
* order. Equivalent to `{type: 'divider'}` in the `items` data API.
|
|
42
|
+
* order. Equivalent to `{type: 'divider'}` in the `items` data API. Host
|
|
43
|
+
* attributes (`id`, `data-*`, `aria-*`) and DOM handlers reach the separator;
|
|
44
|
+
* its role and orientation stay component-owned.
|
|
43
45
|
*
|
|
44
46
|
* @example
|
|
45
47
|
* ```
|
|
@@ -54,9 +56,11 @@ export function DropdownMenuDivider({
|
|
|
54
56
|
xstyle,
|
|
55
57
|
className,
|
|
56
58
|
style,
|
|
57
|
-
ref
|
|
59
|
+
ref,
|
|
60
|
+
...rest
|
|
58
61
|
}) {
|
|
59
62
|
return /*#__PURE__*/_jsx(Divider, {
|
|
63
|
+
...rest,
|
|
60
64
|
ref: ref,
|
|
61
65
|
xstyle: [styles.divider, xstyle],
|
|
62
66
|
className: className ? `${THEME_CLASS_NAME} ${className}` : THEME_CLASS_NAME,
|
|
@@ -22,7 +22,7 @@ export interface TabMenuOption {
|
|
|
22
22
|
*/
|
|
23
23
|
icon?: ReactNode | IconType;
|
|
24
24
|
}
|
|
25
|
-
export interface TabMenuProps extends
|
|
25
|
+
export interface TabMenuProps extends Omit<BaseProps<HTMLButtonElement>, 'role' | 'tabIndex' | 'aria-haspopup' | 'aria-expanded' | 'aria-controls'> {
|
|
26
26
|
ref?: React.Ref<HTMLButtonElement>;
|
|
27
27
|
/**
|
|
28
28
|
* Label for the trigger button and dropdown heading.
|
|
@@ -50,7 +50,7 @@ export interface TabMenuProps extends Pick<BaseProps<HTMLButtonElement>, 'xstyle
|
|
|
50
50
|
* </TabList>
|
|
51
51
|
* ```
|
|
52
52
|
*/
|
|
53
|
-
export declare function TabMenu({ ref, label, options, xstyle, className, style, }: TabMenuProps): React.JSX.Element;
|
|
53
|
+
export declare function TabMenu({ ref, label, options, xstyle, className, style, onClick, ...rest }: TabMenuProps): React.JSX.Element;
|
|
54
54
|
export declare namespace TabMenu {
|
|
55
55
|
var displayName: string;
|
|
56
56
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TabMenu.d.ts","sourceRoot":"","sources":["../../src/TabList/TabMenu.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,EAA6B,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAGxE,OAAO,EAAiB,KAAK,QAAQ,EAAC,MAAM,SAAS,CAAC;AAoBtD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAG5C,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;CAC7B;AAED,MAAM,WAAW,YAAa,SAAQ,IAAI,CACxC,SAAS,CAAC,iBAAiB,CAAC,EAC5B,
|
|
1
|
+
{"version":3,"file":"TabMenu.d.ts","sourceRoot":"","sources":["../../src/TabList/TabMenu.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,EAA6B,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAGxE,OAAO,EAAiB,KAAK,QAAQ,EAAC,MAAM,SAAS,CAAC;AAoBtD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAG5C,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;CAC7B;AAED,MAAM,WAAW,YAAa,SAAQ,IAAI,CACxC,SAAS,CAAC,iBAAiB,CAAC,EAC5B,MAAM,GAAG,UAAU,GAAG,eAAe,GAAG,eAAe,GAAG,eAAe,CAC1E;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AA+KD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,EACtB,GAAG,EACH,KAAK,EACL,OAAO,EACP,MAAM,EACN,SAAS,EACT,KAAK,EACL,OAAO,EACP,GAAG,IAAI,EACR,EAAE,YAAY,qBA6Ld;yBAtMe,OAAO"}
|
package/dist/TabList/TabMenu.js
CHANGED
|
@@ -28,7 +28,7 @@ import { useListFocus } from "../hooks/useListFocus.js";
|
|
|
28
28
|
import { useTabListContext } from "./TabListContext.js";
|
|
29
29
|
import "./tab.markers.stylex.js";
|
|
30
30
|
import { tabScope } from "./tab.markers.stylex.js";
|
|
31
|
-
import { mergeProps } from "../utils/index.js";
|
|
31
|
+
import { composeEventHandlers, mergeProps } from "../utils/index.js";
|
|
32
32
|
import { useMergedRefs } from "../hooks/useMergedRefs.js";
|
|
33
33
|
import { themeProps } from "../utils/themeProps.js";
|
|
34
34
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
@@ -166,7 +166,9 @@ export function TabMenu({
|
|
|
166
166
|
options,
|
|
167
167
|
xstyle,
|
|
168
168
|
className,
|
|
169
|
-
style
|
|
169
|
+
style,
|
|
170
|
+
onClick,
|
|
171
|
+
...rest
|
|
170
172
|
}) {
|
|
171
173
|
const tabListCtx = useTabListContext();
|
|
172
174
|
const menuId = useId();
|
|
@@ -231,6 +233,7 @@ export function TabMenu({
|
|
|
231
233
|
const setButtonRef = useMergedRefs(popover.triggerRef, buttonRef, ref);
|
|
232
234
|
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
233
235
|
children: [/*#__PURE__*/_jsxs("button", {
|
|
236
|
+
...rest,
|
|
234
237
|
ref: setButtonRef,
|
|
235
238
|
type: "button",
|
|
236
239
|
"aria-haspopup": "menu",
|
|
@@ -238,7 +241,7 @@ export function TabMenu({
|
|
|
238
241
|
"aria-controls": menuId,
|
|
239
242
|
"data-tab-menu": "",
|
|
240
243
|
tabIndex: hasSelectedOption ? 0 : -1,
|
|
241
|
-
onClick: handleToggle,
|
|
244
|
+
onClick: composeEventHandlers(handleToggle, onClick),
|
|
242
245
|
...mergeProps(themeProps('tab-menu'), focusOutlineProps.focusVisible(styles.trigger, sizeStyles[size], hasSelectedOption && styles.triggerSelected, tabScope, xstyle), className, style),
|
|
243
246
|
children: [/*#__PURE__*/_jsx("span", {
|
|
244
247
|
"aria-hidden": "true",
|
package/dist/astryx.css
CHANGED
|
@@ -1535,6 +1535,8 @@
|
|
|
1535
1535
|
.xxdn8bs:has(> div > .astryx-layout-content):not(#\#):not(#\#):not(#\#){padding-inline-end:max(0px,calc((100% - var(--layout-content-width)) / 2))}
|
|
1536
1536
|
.xmnmr5y:has(.astryx-nav-icon):not(#\#):not(#\#):not(#\#){padding-inline-start:0}
|
|
1537
1537
|
.x1vvd0s7:has(> div > .astryx-layout-content):not(#\#):not(#\#):not(#\#){padding-inline-start:max(0px,calc((100% - var(--layout-content-width)) / 2))}
|
|
1538
|
+
.xbw113y:dir(rtl):not(#\#):not(#\#):not(#\#){transform:translateX(-100%)}
|
|
1539
|
+
.x1eqdj8u:dir(rtl):not(#\#):not(#\#):not(#\#){transform:translateX(100%)}
|
|
1538
1540
|
.x1xrp5p4:first-child:not(#\#):not(#\#):not(#\#){border-end-start-radius:var(--radius-element)}
|
|
1539
1541
|
.xyf0ibl:first-child:not(#\#):not(#\#):not(#\#){border-inline-start-style:none}
|
|
1540
1542
|
.x1pjv70x:first-child:not(#\#):not(#\#):not(#\#){border-inline-start-width:0}
|
|
@@ -2079,6 +2081,8 @@
|
|
|
2079
2081
|
.xubczrd.xubczrd:where(:not(:disabled,[aria-disabled="true"]))[data-astryx-press="fading"]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#){background-image:var(--_press-paint-image)}
|
|
2080
2082
|
@starting-style{.x1lymnkk.x1lymnkk:is([dir="rtl"] *):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#){transform:translateX(-100%)}}
|
|
2081
2083
|
@starting-style{.x14gflnl.x14gflnl:is([dir="rtl"] *):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#){transform:translateX(100%)}}
|
|
2084
|
+
@starting-style{.xrxqmjf.xrxqmjf:dir(rtl):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#){transform:translateX(-100%)}}
|
|
2085
|
+
@starting-style{.x1r0dqvm.x1r0dqvm:dir(rtl):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#){transform:translateX(100%)}}
|
|
2082
2086
|
@media (forced-colors: active){.x1pjcgc3.x1pjcgc3[data-astryx-press="fading"]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#){background-color:Highlight}}
|
|
2083
2087
|
@media (forced-colors: active){.x1r4mieh.x1r4mieh[data-astryx-press="on"]:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#){background-color:Highlight}}
|
|
2084
2088
|
.x1k48kgn:not(#\#):not(#\#):not(#\#):not(#\#):not(#\#):not(#\#)::after{border-radius:inherit}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/core",
|
|
3
|
-
"version": "0.7.2-canary.
|
|
3
|
+
"version": "0.7.2-canary.9da2d0b",
|
|
4
4
|
"displayName": "Astryx Core",
|
|
5
5
|
"description": "The component library. Accessible, themeable React components with built-in spacing, dark mode, and StyleX styling.",
|
|
6
6
|
"author": "Meta Open Source",
|
|
@@ -792,8 +792,8 @@
|
|
|
792
792
|
"react-dom": ">=19.0.0"
|
|
793
793
|
},
|
|
794
794
|
"devDependencies": {
|
|
795
|
-
"@astryxdesign/a11y-spec": "0.7.2-canary.
|
|
796
|
-
"@astryxdesign/cli": "0.7.2-canary.
|
|
795
|
+
"@astryxdesign/a11y-spec": "0.7.2-canary.9da2d0b",
|
|
796
|
+
"@astryxdesign/cli": "0.7.2-canary.9da2d0b",
|
|
797
797
|
"@babel/cli": "^7.29.7",
|
|
798
798
|
"@babel/core": "^7.29.7",
|
|
799
799
|
"@babel/preset-react": "^7.29.7",
|
|
@@ -239,11 +239,13 @@ Consumer prop syntax and examples remain in `Drawer.doc.mjs`.
|
|
|
239
239
|
- **AR5 — Close affordance.** Drawer provides no close control of its own. When
|
|
240
240
|
rendered, the `DrawerHeader` close action keeps its translated accessible name
|
|
241
241
|
and Button-owned keyboard/focus behavior in both presentations.
|
|
242
|
-
- **AR6 — Direction and motion.** Logical inset placement
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
242
|
+
- **AR6 — Direction and motion.** Logical inset placement and slide-direction
|
|
243
|
+
mirroring follow DOM directionality from the nearest effective `dir` attribute,
|
|
244
|
+
including an explicit local override or an inherited direction. As required by
|
|
245
|
+
`design:bidirectionality`, a region whose direction differs from its ancestor
|
|
246
|
+
describes that direction in DOM `dir`; a CSS-only `direction` declaration is
|
|
247
|
+
not a supported substitute. Motion reduces under `prefers-reduced-motion`
|
|
248
|
+
without changing the final state.
|
|
247
249
|
|
|
248
250
|
## Design relationships
|
|
249
251
|
|
|
@@ -299,7 +301,7 @@ decide future target qualification.
|
|
|
299
301
|
| FR15 | `Drawer.test.tsx` purpose suite | `info`, `form`, `required`; modal and non-modal; a sibling behind a required drawer | A `form` drawer closes on a scrim click, a `required` drawer closes or lets Escape reach the drawer behind it, or its role semantics drift. | `audit:Drawer/behavior` |
|
|
300
302
|
| FR12 | source, `Drawer.doc.mjs`, `DrawerHeader.doc.mjs`, the `DrawerHeader` target test, and current target discovery | start/end root Panel and inherited container context | Current root target/axis or padding reset changes, or the record claims an unreachable child target or decides future admission. | `audit:Drawer/theming` |
|
|
301
303
|
| FR16 | `Drawer.test.tsx` container padding suites; `defineTheme.test.ts` drawer mapping; browser evidence | default, `padding` prop, theme `padding`, lone padded Section child, Layout composition | The published inset differs from the applied padding, the default drawer changes geometry, or the block-end safe area is lost or double-subtracted. | `audit:Drawer/theming` |
|
|
302
|
-
| AR6 |
|
|
304
|
+
| AR6 | `DrawerDirection.test.tsx` DOM-direction and closed/entry parity suites plus exact-head Storybook RTL evidence | start/end; self-applied, inherited, and nested opposite `dir`; closed and opening transforms | Any effective DOM direction or local override moves the panel from a different edge than its logical placement, or closed and opening transforms diverge. | `audit:Drawer/accessibility` |
|
|
303
305
|
|
|
304
306
|
## Decision log
|
|
305
307
|
|
package/src/Drawer/Drawer.tsx
CHANGED
|
@@ -153,8 +153,9 @@ const styles = stylex.create({
|
|
|
153
153
|
rendered: {
|
|
154
154
|
display: 'flex',
|
|
155
155
|
},
|
|
156
|
-
//
|
|
157
|
-
//
|
|
156
|
+
// DOM directionality comes from the nearest effective `dir` attribute. A
|
|
157
|
+
// local override and an inherited region therefore agree with the logical
|
|
158
|
+
// edge the panel is anchored to.
|
|
158
159
|
end: {
|
|
159
160
|
insetInlineEnd: 0,
|
|
160
161
|
insetInlineStart: 'auto',
|
|
@@ -163,7 +164,7 @@ const styles = stylex.create({
|
|
|
163
164
|
borderInlineStartColor: colorVars['--color-border'],
|
|
164
165
|
transform: {
|
|
165
166
|
default: 'translateX(100%)',
|
|
166
|
-
':
|
|
167
|
+
':dir(rtl)': 'translateX(-100%)',
|
|
167
168
|
},
|
|
168
169
|
},
|
|
169
170
|
endOpen: {
|
|
@@ -171,7 +172,7 @@ const styles = stylex.create({
|
|
|
171
172
|
default: 'translateX(0)',
|
|
172
173
|
'@starting-style': {
|
|
173
174
|
default: 'translateX(100%)',
|
|
174
|
-
':
|
|
175
|
+
':dir(rtl)': 'translateX(-100%)',
|
|
175
176
|
},
|
|
176
177
|
},
|
|
177
178
|
},
|
|
@@ -183,7 +184,7 @@ const styles = stylex.create({
|
|
|
183
184
|
borderInlineEndColor: colorVars['--color-border'],
|
|
184
185
|
transform: {
|
|
185
186
|
default: 'translateX(-100%)',
|
|
186
|
-
':
|
|
187
|
+
':dir(rtl)': 'translateX(100%)',
|
|
187
188
|
},
|
|
188
189
|
},
|
|
189
190
|
startOpen: {
|
|
@@ -191,7 +192,7 @@ const styles = stylex.create({
|
|
|
191
192
|
default: 'translateX(0)',
|
|
192
193
|
'@starting-style': {
|
|
193
194
|
default: 'translateX(-100%)',
|
|
194
|
-
':
|
|
195
|
+
':dir(rtl)': 'translateX(100%)',
|
|
195
196
|
},
|
|
196
197
|
},
|
|
197
198
|
},
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file DrawerDirection.test.tsx
|
|
5
|
+
* @input Drawer closed transforms and the matching @starting-style declarations
|
|
6
|
+
* @output Regression coverage for resolved DOM LTR/RTL motion on both logical sides
|
|
7
|
+
* @position Focused direction contract; complements Drawer.test.tsx behavior coverage
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {readFileSync} from 'node:fs';
|
|
11
|
+
import {join} from 'node:path';
|
|
12
|
+
import * as ts from 'typescript';
|
|
13
|
+
import {describe, expect, it} from 'vitest';
|
|
14
|
+
import {render, screen} from '@testing-library/react';
|
|
15
|
+
import {Drawer} from './Drawer';
|
|
16
|
+
|
|
17
|
+
function closedTransform(): string {
|
|
18
|
+
return getComputedStyle(screen.getByRole('dialog', {hidden: true})).transform;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
describe.each([
|
|
22
|
+
{side: 'start' as const, ltr: 'translateX(-100%)', rtl: 'translateX(100%)'},
|
|
23
|
+
{side: 'end' as const, ltr: 'translateX(100%)', rtl: 'translateX(-100%)'},
|
|
24
|
+
])('Drawer direction on side=$side', ({side, ltr, rtl}) => {
|
|
25
|
+
it('uses a self-applied RTL direction', () => {
|
|
26
|
+
render(
|
|
27
|
+
<Drawer
|
|
28
|
+
isOpen={false}
|
|
29
|
+
onOpenChange={() => {}}
|
|
30
|
+
label="Details"
|
|
31
|
+
side={side}
|
|
32
|
+
dir="rtl">
|
|
33
|
+
Content
|
|
34
|
+
</Drawer>,
|
|
35
|
+
);
|
|
36
|
+
expect(closedTransform()).toBe(rtl);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('honors a nearer LTR override inside an RTL page', () => {
|
|
40
|
+
render(
|
|
41
|
+
<div dir="rtl">
|
|
42
|
+
<Drawer
|
|
43
|
+
isOpen={false}
|
|
44
|
+
onOpenChange={() => {}}
|
|
45
|
+
label="Details"
|
|
46
|
+
side={side}
|
|
47
|
+
dir="ltr">
|
|
48
|
+
Content
|
|
49
|
+
</Drawer>
|
|
50
|
+
</div>,
|
|
51
|
+
);
|
|
52
|
+
expect(closedTransform()).toBe(ltr);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const SOURCE = readFileSync(join(__dirname, 'Drawer.tsx'), 'utf8');
|
|
57
|
+
|
|
58
|
+
function styleDefinition(name: string): ts.ObjectLiteralExpression {
|
|
59
|
+
const file = ts.createSourceFile(
|
|
60
|
+
'Drawer.tsx',
|
|
61
|
+
SOURCE,
|
|
62
|
+
ts.ScriptTarget.Latest,
|
|
63
|
+
true,
|
|
64
|
+
ts.ScriptKind.TSX,
|
|
65
|
+
);
|
|
66
|
+
let found: ts.ObjectLiteralExpression | undefined;
|
|
67
|
+
const visit = (node: ts.Node) => {
|
|
68
|
+
if (
|
|
69
|
+
ts.isPropertyAssignment(node) &&
|
|
70
|
+
ts.isIdentifier(node.name) &&
|
|
71
|
+
node.name.text === name &&
|
|
72
|
+
ts.isObjectLiteralExpression(node.initializer)
|
|
73
|
+
) {
|
|
74
|
+
found = node.initializer;
|
|
75
|
+
}
|
|
76
|
+
ts.forEachChild(node, visit);
|
|
77
|
+
};
|
|
78
|
+
visit(file);
|
|
79
|
+
if (found == null) {
|
|
80
|
+
throw new Error(`No style named "${name}" in Drawer.tsx`);
|
|
81
|
+
}
|
|
82
|
+
return found;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function property(style: ts.ObjectLiteralExpression, key: string): string {
|
|
86
|
+
const entry = style.properties.find(
|
|
87
|
+
candidate =>
|
|
88
|
+
ts.isPropertyAssignment(candidate) &&
|
|
89
|
+
(ts.isIdentifier(candidate.name) || ts.isStringLiteral(candidate.name)) &&
|
|
90
|
+
candidate.name.text === key,
|
|
91
|
+
);
|
|
92
|
+
if (entry == null) {
|
|
93
|
+
throw new Error(`No "${key}" in ${style.getText().slice(0, 40)}…`);
|
|
94
|
+
}
|
|
95
|
+
return (entry as ts.PropertyAssignment).initializer.getText();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
describe.each([
|
|
99
|
+
{
|
|
100
|
+
side: 'start',
|
|
101
|
+
closed: 'start',
|
|
102
|
+
open: 'startOpen',
|
|
103
|
+
ltr: 'translateX(-100%)',
|
|
104
|
+
rtl: 'translateX(100%)',
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
side: 'end',
|
|
108
|
+
closed: 'end',
|
|
109
|
+
open: 'endOpen',
|
|
110
|
+
ltr: 'translateX(100%)',
|
|
111
|
+
rtl: 'translateX(-100%)',
|
|
112
|
+
},
|
|
113
|
+
])('Drawer $side entry declaration', ({closed, open, ltr, rtl}) => {
|
|
114
|
+
it('parks closed on the computed logical edge', () => {
|
|
115
|
+
const transform = property(styleDefinition(closed), 'transform');
|
|
116
|
+
expect(transform).toContain(`default: '${ltr}'`);
|
|
117
|
+
expect(transform).toContain(`':dir(rtl)': '${rtl}'`);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('starts opening from the same computed logical edge', () => {
|
|
121
|
+
const transform = property(styleDefinition(open), 'transform');
|
|
122
|
+
expect(transform).toContain("default: 'translateX(0)'");
|
|
123
|
+
expect(transform).toContain('@starting-style');
|
|
124
|
+
expect(transform).toContain(`default: '${ltr}'`);
|
|
125
|
+
expect(transform).toContain(`':dir(rtl)': '${rtl}'`);
|
|
126
|
+
});
|
|
127
|
+
});
|
|
@@ -50,6 +50,19 @@ describe('DrawerHeader', () => {
|
|
|
50
50
|
expect(names).toEqual(['Back', 'Edit', 'Close']);
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
+
it('renders 0 values inside their start and end content slots', () => {
|
|
54
|
+
const {container} = render(
|
|
55
|
+
<DrawerHeader title="Details" startContent={0} endContent={0} />,
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
expect(
|
|
59
|
+
container.querySelector('.astryx-drawer-header-start-content'),
|
|
60
|
+
).toHaveTextContent('0');
|
|
61
|
+
expect(
|
|
62
|
+
container.querySelector('.astryx-drawer-header-end-content'),
|
|
63
|
+
).toHaveTextContent('0');
|
|
64
|
+
});
|
|
65
|
+
|
|
53
66
|
it('renders a 0 subtitle and skips an empty one', () => {
|
|
54
67
|
const {rerender, container} = render(
|
|
55
68
|
<DrawerHeader title="Details" subtitle={0} />,
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @file DrawerHeader.tsx
|
|
7
|
-
* @input Uses React, StyleX, LayoutHeader, Button, Icon, Heading, Text, i18n, BaseProps, mergeProps, themeProps
|
|
7
|
+
* @input Uses React, StyleX, LayoutHeader, Button, Icon, Heading, Text, i18n, BaseProps, isRenderable, mergeProps, themeProps
|
|
8
8
|
* @output Exports DrawerHeader component and DrawerHeaderProps
|
|
9
9
|
* @position Drawer header; composed in a Layout header slot inside Drawer, tested by DrawerHeader.test.tsx
|
|
10
10
|
*
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* - /packages/cli/assets/templates/blocks/components/Drawer/ (showcase blocks)
|
|
23
23
|
* - /packages/cli/assets/templates/blocks/components/DrawerHeader/ (showcase blocks)
|
|
24
24
|
* - /apps/storybook/stories/Drawer.stories.tsx (examples and visual coverage)
|
|
25
|
+
* - /apps/storybook/stories/DrawerHeader.stories.tsx (component audit fixture)
|
|
25
26
|
*/
|
|
26
27
|
|
|
27
28
|
import type {ReactNode} from 'react';
|
|
@@ -34,7 +35,7 @@ import {Icon} from '../Icon';
|
|
|
34
35
|
import {LayoutHeader} from '../Layout';
|
|
35
36
|
import {Text} from '../Text';
|
|
36
37
|
import {useTranslator} from '../i18n';
|
|
37
|
-
import {mergeProps, themeProps} from '../utils';
|
|
38
|
+
import {isRenderable, mergeProps, themeProps} from '../utils';
|
|
38
39
|
|
|
39
40
|
const styles = stylex.create({
|
|
40
41
|
container: {
|
|
@@ -147,10 +148,9 @@ export function DrawerHeader({
|
|
|
147
148
|
...rest
|
|
148
149
|
}: DrawerHeaderProps) {
|
|
149
150
|
const t = useTranslator();
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const
|
|
153
|
-
subtitle != null && typeof subtitle !== 'boolean' && subtitle !== '';
|
|
151
|
+
const hasSubtitle = isRenderable(subtitle);
|
|
152
|
+
const hasStartContent = isRenderable(startContent);
|
|
153
|
+
const hasEndContent = isRenderable(endContent);
|
|
154
154
|
const shouldCompensateEndBlock =
|
|
155
155
|
endContentEdgeCompensation == null
|
|
156
156
|
? onOpenChange != null
|
|
@@ -175,7 +175,7 @@ export function DrawerHeader({
|
|
|
175
175
|
themeProps('drawer-header'),
|
|
176
176
|
stylex.props(styles.container),
|
|
177
177
|
)}>
|
|
178
|
-
{
|
|
178
|
+
{hasStartContent && (
|
|
179
179
|
<div
|
|
180
180
|
{...mergeProps(
|
|
181
181
|
themeProps('drawer-header-start-content'),
|
|
@@ -196,7 +196,7 @@ export function DrawerHeader({
|
|
|
196
196
|
</Text>
|
|
197
197
|
)}
|
|
198
198
|
</div>
|
|
199
|
-
{(
|
|
199
|
+
{(hasEndContent || onOpenChange != null) && (
|
|
200
200
|
<div
|
|
201
201
|
{...mergeProps(
|
|
202
202
|
themeProps('drawer-header-end-content'),
|