@astryxdesign/core 0.6.3-canary.ea2f048 → 0.6.3

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.
@@ -70,25 +70,6 @@ export interface ChatLayoutProps extends BaseProps<HTMLDivElement> {
70
70
  */
71
71
  density?: Density;
72
72
  }
73
- /**
74
- * Layout shell for a full chat interface: messages in page flow, composer
75
- * docked to the bottom behind a frosted glass layer, with auto-scroll and a
76
- * scroll-to-bottom button wired in.
77
- *
78
- * @example
79
- * ```
80
- * <ChatLayout
81
- * density="spacious"
82
- * composer={<ChatComposer onSubmit={send} />}
83
- * emptyState={<EmptyState title="No messages yet" />}>
84
- * <ChatMessageList>
85
- * <ChatMessage sender="assistant">
86
- * <ChatMessageBubble>How can I help?</ChatMessageBubble>
87
- * </ChatMessage>
88
- * </ChatMessageList>
89
- * </ChatLayout>
90
- * ```
91
- */
92
73
  export declare function ChatLayout({ children, composer, density, emptyState, scrollButton, scrollRef: externalScrollRef, xstyle, className, style, 'data-testid': testId, ref, ...rest }: ChatLayoutProps): import("react").JSX.Element;
93
74
  export declare namespace ChatLayout {
94
75
  var displayName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"ChatLayout.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatLayout.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAC,KAAK,SAAS,EAAkB,MAAM,OAAO,CAAC;AAGtD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAc5C,KAAK,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;AAEnD,MAAM,WAAW,eAAgB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAChE,yCAAyC;IACzC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEhC;;;OAGG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;;OAGG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IAEvB;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAEhC;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAEhD;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA4KD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,QAAQ,EACR,OAAoB,EACpB,UAAU,EACV,YAAY,EACZ,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EACN,SAAS,EACT,KAAK,EACL,aAAa,EAAE,MAAM,EACrB,GAAG,EACH,GAAG,IAAI,EACR,EAAE,eAAe,+BA4GjB;yBAzHe,UAAU"}
1
+ {"version":3,"file":"ChatLayout.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatLayout.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAC,KAAK,SAAS,EAAkB,MAAM,OAAO,CAAC;AAGtD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAc5C,KAAK,OAAO,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;AAEnD,MAAM,WAAW,eAAgB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAChE,yCAAyC;IACzC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEhC;;;OAGG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;;OAGG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;OAEG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IAEvB;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAEhC;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAEhD;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA4KD,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,QAAQ,EACR,OAAoB,EACpB,UAAU,EACV,YAAY,EACZ,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EACN,SAAS,EACT,KAAK,EACL,aAAa,EAAE,MAAM,EACrB,GAAG,EACH,GAAG,IAAI,EACR,EAAE,eAAe,+BA4GjB;yBAzHe,UAAU"}
@@ -184,25 +184,6 @@ function hasVisibleContent(children) {
184
184
  // Component
185
185
  // =============================================================================
186
186
 
187
- /**
188
- * Layout shell for a full chat interface: messages in page flow, composer
189
- * docked to the bottom behind a frosted glass layer, with auto-scroll and a
190
- * scroll-to-bottom button wired in.
191
- *
192
- * @example
193
- * ```
194
- * <ChatLayout
195
- * density="spacious"
196
- * composer={<ChatComposer onSubmit={send} />}
197
- * emptyState={<EmptyState title="No messages yet" />}>
198
- * <ChatMessageList>
199
- * <ChatMessage sender="assistant">
200
- * <ChatMessageBubble>How can I help?</ChatMessageBubble>
201
- * </ChatMessage>
202
- * </ChatMessageList>
203
- * </ChatLayout>
204
- * ```
205
- */
206
187
  export function ChatLayout({
207
188
  children,
208
189
  composer,
@@ -1 +1 @@
1
- {"version":3,"file":"ChatLayoutScrollButton.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatLayoutScrollButton.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAa1B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAS5C,MAAM,WAAW,2BAA4B,SAAQ,IAAI,CACvD,SAAS,CAAC,cAAc,CAAC,EACzB,SAAS,CACV;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,qCAAqC;IACrC,SAAS,EAAE,OAAO,CAAC;IACnB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAsED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,GAAG,EACH,SAAS,EACT,KAAK,EACL,OAAO,EACP,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,IAAI,EACR,EAAE,2BAA2B,qBAkC7B;yBA3Ce,sBAAsB"}
1
+ {"version":3,"file":"ChatLayoutScrollButton.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatLayoutScrollButton.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAY1B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAS5C,MAAM,WAAW,2BAA4B,SAAQ,IAAI,CACvD,SAAS,CAAC,cAAc,CAAC,EACzB,SAAS,CACV;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,qCAAqC;IACrC,SAAS,EAAE,OAAO,CAAC;IACnB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AA2DD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,GAAG,EACH,SAAS,EACT,KAAK,EACL,OAAO,EACP,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,IAAI,EACR,EAAE,2BAA2B,qBAkC7B;yBA3Ce,sBAAsB"}
@@ -18,7 +18,7 @@
18
18
  import React from 'react';
19
19
  import * as stylex from '@stylexjs/stylex';
20
20
  import "../theme/tokens.stylex.js";
21
- import { colorVars, spacingVars, radiusVars, shadowVars, sizeVars, durationVars, easeVars } from "../theme/tokens.stylex.js";
21
+ import { colorVars, spacingVars, radiusVars, shadowVars, durationVars, easeVars } from "../theme/tokens.stylex.js";
22
22
  import { Icon } from "../Icon/index.js";
23
23
  import { Button } from "../Button/index.js";
24
24
  import { mergeProps } from "../utils/index.js";
@@ -82,16 +82,16 @@ export function ChatLayoutScrollButton({
82
82
  children: /*#__PURE__*/_jsx("div", {
83
83
  ...{
84
84
  0: {
85
- className: "xawy1a7 xb3r6kr xjspbzw x1prclbq x14hfi27 x1ueg155 xrgg2z9 xlr8y92 x2rcmwa x12w9bfk xg01cxk x47corl xlshs6z x1jys5uj"
85
+ className: "xawy1a7 xb3r6kr xjspbzw x1prclbq x14hfi27 x10w6t97 x1apppo2 xlr8y92 x2rcmwa x12w9bfk xg01cxk x47corl x1x67gh"
86
86
  },
87
87
  2: {
88
- className: "xawy1a7 xb3r6kr xjspbzw x1prclbq x14hfi27 x1ueg155 xrgg2z9 xlr8y92 x2rcmwa x12w9bfk x1hc1fzr x67bb7w xnpuxes x1jys5uj"
88
+ className: "xawy1a7 xb3r6kr xjspbzw x1prclbq x14hfi27 x10w6t97 x1apppo2 xlr8y92 x2rcmwa x12w9bfk x1hc1fzr x67bb7w x1x67gh"
89
89
  },
90
90
  1: {
91
- className: "xawy1a7 xb3r6kr xjspbzw x1prclbq x14hfi27 x1ueg155 xrgg2z9 xlr8y92 x2rcmwa x12w9bfk xg01cxk x47corl xlshs6z x1ncir08"
91
+ className: "xawy1a7 xb3r6kr xjspbzw x1prclbq x14hfi27 x10w6t97 x1apppo2 xlr8y92 x2rcmwa x12w9bfk xg01cxk x47corl x1ncir08"
92
92
  },
93
93
  3: {
94
- className: "xawy1a7 xb3r6kr xjspbzw x1prclbq x14hfi27 x1ueg155 xrgg2z9 xlr8y92 x2rcmwa x12w9bfk x1hc1fzr x67bb7w xnpuxes x1ncir08"
94
+ className: "xawy1a7 xb3r6kr xjspbzw x1prclbq x14hfi27 x10w6t97 x1apppo2 xlr8y92 x2rcmwa x12w9bfk x1hc1fzr x67bb7w x1ncir08"
95
95
  }
96
96
  }[!!isVisible << 1 | !!label << 0],
97
97
  children: /*#__PURE__*/_jsx(Button, {
package/dist/astryx.css CHANGED
@@ -1281,7 +1281,7 @@
1281
1281
  .xnpjden:not(#\#):not(#\#):not(#\#){transition-property:opacity,background-color}
1282
1282
  .xsm4mo9:not(#\#):not(#\#):not(#\#){transition-property:opacity,display,overlay}
1283
1283
  .x1n1p2mu:not(#\#):not(#\#):not(#\#){transition-property:opacity,position}
1284
- .xrgg2z9:not(#\#):not(#\#):not(#\#){transition-property:opacity,transform,max-width,visibility}
1284
+ .x1apppo2:not(#\#):not(#\#):not(#\#){transition-property:opacity,transform,max-width}
1285
1285
  .x4bbghf:not(#\#):not(#\#):not(#\#){transition-property:opacity,transform,overlay,display}
1286
1286
  .x6o7n8i:not(#\#):not(#\#):not(#\#){transition-property:opacity,transform}
1287
1287
  .xxup5nn:not(#\#):not(#\#):not(#\#){transition-property:opacity,visibility,transform}
@@ -1656,6 +1656,7 @@
1656
1656
  .x55n99s:not(#\#):not(#\#):not(#\#):not(#\#){max-width:15em}
1657
1657
  .x1ncir08:not(#\#):not(#\#):not(#\#):not(#\#){max-width:200px}
1658
1658
  .xw5ewwj:not(#\#):not(#\#):not(#\#):not(#\#){max-width:300px}
1659
+ .x1x67gh:not(#\#):not(#\#):not(#\#):not(#\#){max-width:32px}
1659
1660
  .xxc7z9f:not(#\#):not(#\#):not(#\#):not(#\#){max-width:360px}
1660
1661
  .x1j9u4d2:not(#\#):not(#\#):not(#\#):not(#\#){max-width:400px}
1661
1662
  .x17fpy1y:not(#\#):not(#\#):not(#\#):not(#\#){max-width:480px}
@@ -1670,7 +1671,6 @@
1670
1671
  .x1m1aaou:not(#\#):not(#\#):not(#\#):not(#\#){max-width:min(960px,calc(100dvw - var(--spacing-4)))}
1671
1672
  .x1x1rfll:not(#\#):not(#\#):not(#\#):not(#\#){max-width:none}
1672
1673
  .xjl2t3p:not(#\#):not(#\#):not(#\#):not(#\#){max-width:var(--layout-content-width,none)}
1673
- .x1jys5uj:not(#\#):not(#\#):not(#\#):not(#\#){max-width:var(--size-element-md)}
1674
1674
  .xf68679:not(#\#):not(#\#):not(#\#):not(#\#){max-width:var(--x-maxWidth)}
1675
1675
  .x2lwn1j:not(#\#):not(#\#):not(#\#):not(#\#){min-height:0}
1676
1676
  .x1us19tq:not(#\#):not(#\#):not(#\#):not(#\#){min-height:100%}
package/dist/index.d.ts CHANGED
@@ -107,7 +107,6 @@ export * from './Skeleton';
107
107
  export * from './StatusDot';
108
108
  export * from './Spinner';
109
109
  export * from './Timestamp';
110
- export * from './Timer';
111
110
  export * from './Overlay';
112
111
  export * from './Outline';
113
112
  export * from './OverflowList';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -133,9 +133,6 @@ export * from "./Spinner/index.js";
133
133
  // Timestamp display
134
134
  export * from "./Timestamp/index.js";
135
135
 
136
- // Elapsed timer display
137
- export * from "./Timer/index.js";
138
-
139
136
  // Overlay
140
137
  export * from "./Overlay/index.js";
141
138
  export * from "./Outline/index.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astryxdesign/core",
3
- "version": "0.6.3-canary.ea2f048",
3
+ "version": "0.6.3",
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",
@@ -539,11 +539,6 @@
539
539
  "types": "./dist/TimeInput/index.d.ts",
540
540
  "default": "./dist/TimeInput/index.js"
541
541
  },
542
- "./Timer": {
543
- "source": "./src/Timer/index.ts",
544
- "types": "./dist/Timer/index.d.ts",
545
- "default": "./dist/Timer/index.js"
546
- },
547
542
  "./Timestamp": {
548
543
  "source": "./src/Timestamp/index.ts",
549
544
  "types": "./dist/Timestamp/index.d.ts",
@@ -692,8 +687,6 @@
692
687
  "react-dom": ">=19.0.0"
693
688
  },
694
689
  "devDependencies": {
695
- "@astryxdesign/a11y-spec": "0.6.3-canary.ea2f048",
696
- "@astryxdesign/cli": "0.6.3-canary.ea2f048",
697
690
  "@babel/cli": "^7.29.7",
698
691
  "@babel/core": "^7.29.7",
699
692
  "@babel/preset-react": "^7.29.7",
@@ -703,7 +696,9 @@
703
696
  "@testing-library/dom": "^10.0.0",
704
697
  "@testing-library/jest-dom": "^6.6.0",
705
698
  "@testing-library/react": "^16.3.2",
706
- "@types/babel__core": "^7.20.5"
699
+ "@types/babel__core": "^7.20.5",
700
+ "@astryxdesign/a11y-spec": "0.0.0",
701
+ "@astryxdesign/cli": "0.6.3"
707
702
  },
708
703
  "dependencies": {
709
704
  "intl-messageformat": "^11.2.9"
@@ -6,7 +6,7 @@ export const docs = {
6
6
  name: 'ChatLayout',
7
7
  subComponentOf: 'Chat',
8
8
  displayName: 'Chat Layout',
9
- description: 'Layout shell for full chat interfaces. Messages flow in normal page flow, composer is fixed to the bottom with a frosted glass dock. Set density (compact/balanced/spacious) to control spacing, message max-width, and blur layer sizing. Includes built-in auto-scroll, a "New messages" scroll-to-bottom button, and a frosted glass blur layer behind the composer. By default the layout root is the scroll container; pass scrollRef to delegate scrolling to a parent element or the document body.',
9
+ description: 'Layout shell for full chat interfaces. Messages flow in normal page flow, composer is fixed to the bottom with a frosted glass dock. Adapts density (compact/balanced/spacious) automatically via container width observation. Includes built-in auto-scroll, a "New messages" scroll-to-bottom button, and a frosted glass blur layer behind the composer. By default the layout root is the scroll container; pass scrollRef to delegate scrolling to a parent element or the document body.',
10
10
  props: [
11
11
  {
12
12
  name: 'children',
@@ -53,15 +53,9 @@ export const docs = {
53
53
  type: 'React.RefObject<HTMLElement | null>',
54
54
  description: 'External scroll container ref. When provided, auto-scroll and scroll-to-bottom target this element instead of the layout root. Use when the chat is embedded in a page where a parent element or the document body scrolls.',
55
55
  },
56
- {
57
- name: 'density',
58
- type: "'compact' | 'balanced' | 'spacious'",
59
- description: 'Visual density: controls dock padding, message-area max-width and inline padding, and the height of the frosted glass blur layer.',
60
- default: "'balanced'",
61
- },
62
56
  ],
63
57
  usage: {
64
- description: 'ChatLayout is the layout shell for full-page chat interfaces. It renders messages in normal page flow and docks the composer to the bottom with a frosted glass blur layer. Set the density prop to control spacing; it defaults to balanced. Use it to wrap ChatMessageList and ChatComposer for a complete chat experience with built-in auto-scroll and a scroll-to-bottom button.',
58
+ description: 'ChatLayout is the layout shell for full-page chat interfaces. It renders messages in normal page flow and docks the composer to the bottom with a frosted glass blur layer. Density adapts automatically via container width observation. Use it to wrap ChatMessageList and ChatComposer for a complete chat experience with built-in auto-scroll and a scroll-to-bottom button.',
65
59
  bestPractices: [
66
60
  {
67
61
  guidance: true,
@@ -117,21 +111,20 @@ export const docs = {
117
111
  export const docsZh = {
118
112
  name: 'ChatLayout',
119
113
  displayName: 'Chat Layout',
120
- description: '完整聊天界面的布局外壳。消息在页面中自然流动,编写器固定在底部,带有毛玻璃效果。通过 density 属性控制密度。',
114
+ description: '完整聊天界面的布局外壳。消息在页面中自然流动,编写器固定在底部,带有毛玻璃效果。通过容器宽度自动适配密度。',
121
115
  propDescriptions: {
122
116
  children: '消息内容,通常是 ChatMessageList。在页面中自然流动。',
123
117
  composer: '编写器元素,通常是 ChatComposer。固定在底部,带有毛玻璃底座。',
124
118
  emptyState: '子元素为空时显示的内容。',
125
119
  scrollButton: '编写器上方的滚动到底部按钮。默认使用 ChatLayoutScrollButton。传入 null 隐藏。',
126
120
  scrollRef: '外部滚动容器引用。提供时,自动滚动和滚动到底部将目标指向此元素。',
127
- density: '视觉密度:控制底座内边距、消息区最大宽度和毛玻璃层高度。',
128
121
  },
129
122
  };
130
123
 
131
124
  export const docsDense = {
132
125
  name: 'ChatLayout',
133
126
  displayName: 'Chat Layout',
134
- description: 'layout shell for full chat; msgs in page flow, composer fixed bottom w/ frosted glass dock; density prop (default balanced); scrollRef delegates to parent/body',
127
+ description: 'layout shell for full chat; msgs in page flow, composer fixed bottom w/ frosted glass dock; auto density via container width; scrollRef delegates to parent/body',
135
128
  usage: {
136
129
  bestPractices: [
137
130
  {guidance: true, description: 'Pass ChatMessageList as children and ChatComposer as composer prop for complete chat.'},
@@ -147,6 +140,5 @@ export const docsDense = {
147
140
  emptyState: 'content when children empty',
148
141
  scrollButton: 'scroll-to-bottom btn; defaults to ChatLayoutScrollButton; pass null to hide',
149
142
  scrollRef: 'external scroll container ref; targets parent/body instead of layout root',
150
- density: 'visual density; dock padding, message max-width, blur height',
151
143
  },
152
144
  };
@@ -2,7 +2,6 @@
2
2
 
3
3
  import {describe, it, expect, vi, beforeEach, afterEach} from 'vitest';
4
4
  import {act, render, screen} from '@testing-library/react';
5
- import userEvent from '@testing-library/user-event';
6
5
  import {ChatLayout} from './ChatLayout';
7
6
  import {ChatMessageList} from './ChatMessageList';
8
7
  import {ChatMessage} from './ChatMessage';
@@ -104,33 +103,6 @@ describe('ChatLayout', () => {
104
103
  });
105
104
  });
106
105
 
107
- // ---------------------------------------------------------------------------
108
- // Keyboard reachability of the default scroll-to-bottom button
109
- //
110
- // At rest the layout is neither scrolled up nor holding new messages, so the
111
- // default ChatLayoutScrollButton renders in its hidden state. It is still in
112
- // the DOM, and it is the first control in the dock — ahead of the composer.
113
- // A control nobody can see must not be a tab stop: WCAG 2.2 SC 2.4.7 requires
114
- // a visible focus indicator wherever focus can land, and the hidden pill paints
115
- // nothing. `opacity: 0` and `pointer-events: none` do not remove an element
116
- // from sequential focus navigation; only visibility/display/inert do.
117
- // ---------------------------------------------------------------------------
118
-
119
- describe('ChatLayout — default scroll button keyboard reachability', () => {
120
- it('does not make the resting scroll-to-bottom button the first tab stop', async () => {
121
- const user = userEvent.setup();
122
- render(
123
- <ChatLayout composer={<button type="button">Send</button>}>
124
- <div>msg</div>
125
- </ChatLayout>,
126
- );
127
-
128
- await user.tab();
129
-
130
- expect(screen.getByRole('button', {name: 'Send'})).toHaveFocus();
131
- });
132
- });
133
-
134
106
  // ---------------------------------------------------------------------------
135
107
  // Self-scroll layout contract (#2573)
136
108
  //
@@ -268,25 +268,6 @@ function hasVisibleContent(children: ReactNode): boolean {
268
268
  // Component
269
269
  // =============================================================================
270
270
 
271
- /**
272
- * Layout shell for a full chat interface: messages in page flow, composer
273
- * docked to the bottom behind a frosted glass layer, with auto-scroll and a
274
- * scroll-to-bottom button wired in.
275
- *
276
- * @example
277
- * ```
278
- * <ChatLayout
279
- * density="spacious"
280
- * composer={<ChatComposer onSubmit={send} />}
281
- * emptyState={<EmptyState title="No messages yet" />}>
282
- * <ChatMessageList>
283
- * <ChatMessage sender="assistant">
284
- * <ChatMessageBubble>How can I help?</ChatMessageBubble>
285
- * </ChatMessage>
286
- * </ChatMessageList>
287
- * </ChatLayout>
288
- * ```
289
- */
290
271
  export function ChatLayout({
291
272
  children,
292
273
  composer,
@@ -2,7 +2,6 @@
2
2
 
3
3
  import {describe, it, expect} from 'vitest';
4
4
  import {render, screen} from '@testing-library/react';
5
- import userEvent from '@testing-library/user-event';
6
5
  import {ChatLayoutScrollButton} from './ChatLayoutScrollButton';
7
6
 
8
7
  describe('ChatLayoutScrollButton', () => {
@@ -53,34 +52,4 @@ describe('ChatLayoutScrollButton', () => {
53
52
  expect(root).toHaveAttribute('data-custom', 'x');
54
53
  expect(root).toHaveAttribute('id', 'scroll-1');
55
54
  });
56
-
57
- // The hidden state paints nothing, so focus landing on it would have no
58
- // visible indicator (WCAG 2.2 SC 2.4.7). `opacity: 0` and
59
- // `pointer-events: none` suppress paint and the pointer but leave the button
60
- // in sequential focus navigation, so the hidden state must also stop being
61
- // focusable — without costing the visible state its keyboard access.
62
- it('is keyboard reachable while visible', async () => {
63
- const user = userEvent.setup();
64
- render(<ChatLayoutScrollButton isVisible onClick={() => {}} />);
65
-
66
- await user.tab();
67
-
68
- expect(
69
- screen.getByRole('button', {name: 'Scroll to bottom'}),
70
- ).toHaveFocus();
71
- });
72
-
73
- it('is not keyboard reachable while hidden', async () => {
74
- const user = userEvent.setup();
75
- render(
76
- <>
77
- <ChatLayoutScrollButton isVisible={false} onClick={() => {}} />
78
- <button type="button">After</button>
79
- </>,
80
- );
81
-
82
- await user.tab();
83
-
84
- expect(screen.getByRole('button', {name: 'After'})).toHaveFocus();
85
- });
86
55
  });
@@ -23,7 +23,6 @@ import {
23
23
  spacingVars,
24
24
  radiusVars,
25
25
  shadowVars,
26
- sizeVars,
27
26
  durationVars,
28
27
  easeVars,
29
28
  } from '../theme/tokens.stylex';
@@ -68,14 +67,8 @@ const styles = stylex.create({
68
67
  borderRadius: radiusVars['--radius-full'],
69
68
  backgroundColor: colorVars['--color-background-popover'],
70
69
  boxShadow: shadowVars['--shadow-med'],
71
- // The pill clips its own content, so it must track the height of the
72
- // md Button it wraps. A literal would clip that Button under any theme
73
- // that retunes the element scale.
74
- height: sizeVars['--size-element-md'],
75
- // `visibility` rides the same transition so the fade-out still plays:
76
- // it flips to `visible` immediately on the way in and only at the end
77
- // of the duration on the way out.
78
- transitionProperty: 'opacity, transform, max-width, visibility',
70
+ height: '32px',
71
+ transitionProperty: 'opacity, transform, max-width',
79
72
  transitionTimingFunction: easeVars['--ease-standard'],
80
73
  transitionDuration: {
81
74
  default: durationVars['--duration-fast-max'],
@@ -85,19 +78,14 @@ const styles = stylex.create({
85
78
  hidden: {
86
79
  opacity: 0,
87
80
  pointerEvents: 'none',
88
- // The hidden pill paints nothing, so focus landing on it would have no
89
- // visible indicator (WCAG 2.2 SC 2.4.7). `opacity` and `pointer-events`
90
- // leave the button in sequential focus navigation; `visibility` removes it.
91
- visibility: 'hidden',
92
- maxWidth: sizeVars['--size-element-md'],
81
+ maxWidth: '32px',
93
82
  },
94
83
  visible: {
95
84
  opacity: 1,
96
85
  pointerEvents: 'auto',
97
- visibility: 'visible',
98
86
  },
99
87
  collapsed: {
100
- maxWidth: sizeVars['--size-element-md'],
88
+ maxWidth: '32px',
101
89
  },
102
90
  expanded: {
103
91
  maxWidth: '200px',
package/src/index.ts CHANGED
@@ -161,9 +161,6 @@ export * from './Spinner';
161
161
  // Timestamp display
162
162
  export * from './Timestamp';
163
163
 
164
- // Elapsed timer display
165
- export * from './Timer';
166
-
167
164
  // Overlay
168
165
  export * from './Overlay';
169
166
  export * from './Outline';
@@ -182,6 +182,12 @@
182
182
  --text-4xl: var(--font-size-4xl);
183
183
  --text-5xl: var(--font-size-5xl);
184
184
 
185
+ /* --- Font weights --- */
186
+ --font-weight-normal: var(--font-weight-normal);
187
+ --font-weight-medium: var(--font-weight-medium);
188
+ --font-weight-semibold: var(--font-weight-semibold);
189
+ --font-weight-bold: var(--font-weight-bold);
190
+
185
191
  /* =========================================================================
186
192
  * Border radius
187
193
  *
@@ -1,49 +0,0 @@
1
- import type { BaseProps } from '../BaseProps';
2
- import type { TextColor, TextSize, TextType, TextWeight } from '../theme/types';
3
- export type TimerFormat = 'elapsed' | 'clock';
4
- export interface TimerProps extends Omit<BaseProps<HTMLTimeElement>, 'dateTime'> {
5
- /** Ref forwarded to the rendered `<time>` element. */
6
- ref?: React.Ref<HTMLTimeElement>;
7
- /**
8
- * Unix time in milliseconds when the measured operation began. Omit it to
9
- * start counting from this Timer's mount.
10
- */
11
- startTime?: number;
12
- /**
13
- * Standard duration representation.
14
- * @default 'elapsed'
15
- */
16
- format?: TimerFormat;
17
- /**
18
- * Semantic text type. Matches Timestamp typography behavior.
19
- * @default 'supporting'
20
- */
21
- type?: TextType;
22
- /** Explicit font size override. Overrides the size from `type`. */
23
- size?: TextSize;
24
- /**
25
- * Text color.
26
- * @default 'secondary'
27
- */
28
- color?: TextColor;
29
- /** Font weight override. */
30
- weight?: TextWeight;
31
- }
32
- /**
33
- * Displays a standardized elapsed duration without scheduling React tick renders.
34
- *
35
- * Timer writes changing text and its ISO 8601 duration directly to the owned
36
- * `<time>` node. Use `elapsed` for compact duration text or `clock` for a
37
- * stopwatch-like reading.
38
- *
39
- * @example
40
- * ```
41
- * <Timer />
42
- * <Timer format="clock" />
43
- * ```
44
- */
45
- export declare function Timer({ startTime, format, type, size, color, weight, ref, xstyle, className, style, ...rest }: TimerProps): import("react").JSX.Element;
46
- export declare namespace Timer {
47
- var displayName: string;
48
- }
49
- //# sourceMappingURL=Timer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Timer.d.ts","sourceRoot":"","sources":["../../src/Timer/Timer.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAG5C,OAAO,KAAK,EAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAC,MAAM,gBAAgB,CAAC;AAsB9E,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;AA8E9C,MAAM,WAAW,UAAW,SAAQ,IAAI,CACtC,SAAS,CAAC,eAAe,CAAC,EAC1B,UAAU,CACX;IACC,sDAAsD;IACtD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACjC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;OAGG;IACH,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,mEAAmE;IACnE,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,KAAK,CAAC,EACpB,SAAS,EACT,MAAkB,EAClB,IAAmB,EACnB,IAAI,EACJ,KAAmB,EACnB,MAAM,EACN,GAAG,EACH,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,IAAI,EACR,EAAE,UAAU,+BA0EZ;yBAtFe,KAAK"}
@@ -1,158 +0,0 @@
1
- // Copyright (c) Meta Platforms, Inc. and affiliates.
2
-
3
- 'use client';
4
-
5
- /**
6
- * @file Timer.tsx
7
- * @input Uses an optional start time, standardized format, Timestamp typography, BaseProps, and React ref
8
- * @output Exports Timer, TimerProps, and TimerFormat with non-rendering elapsed-time updates
9
- * @position Core content primitive for elapsed duration in active operations
10
- *
11
- * SYNC: When modified, update these files to stay in sync:
12
- * - /packages/core/src/Timer/Timer.spec.md
13
- * - /packages/core/src/Timer/Timer.doc.mjs
14
- * - /packages/core/src/Timer/Timer.test.tsx
15
- * - /packages/core/src/Timer/index.ts
16
- * - /apps/storybook/stories/Timer.stories.tsx
17
- * - /packages/cli/assets/templates/blocks/components/Timer/
18
- */
19
- import { useEffect, useRef, useState } from 'react';
20
- import * as stylex from '@stylexjs/stylex';
21
- import { useMergedRefs } from "../hooks/useMergedRefs.js";
22
- import { Text } from "../Text/index.js";
23
- import { mergeProps } from "../utils/index.js";
24
- import { themeProps } from "../utils/themeProps.js";
25
- import { jsx as _jsx } from "react/jsx-runtime";
26
- const ONE_SECOND_MS = 1000;
27
- const ONE_MINUTE_MS = 60 * ONE_SECOND_MS;
28
- const ONE_HOUR_SECONDS = 60 * 60;
29
- const MAX_TIMEOUT_MS = 2_147_483_647;
30
- function pad(value) {
31
- return String(value).padStart(2, '0');
32
- }
33
- function resolveFormat(format) {
34
- return format === 'clock' ? 'clock' : 'elapsed';
35
- }
36
- function getElapsedMilliseconds(now, startTime) {
37
- return Math.max(0, now - startTime);
38
- }
39
- function getPresentation(elapsedMilliseconds, format) {
40
- const elapsedSeconds = Math.floor(elapsedMilliseconds / ONE_SECOND_MS);
41
- if (format === 'clock') {
42
- const hours = Math.floor(elapsedSeconds / ONE_HOUR_SECONDS);
43
- const minutes = Math.floor(elapsedSeconds % ONE_HOUR_SECONDS / 60);
44
- const seconds = elapsedSeconds % 60;
45
- return {
46
- dateTime: `PT${elapsedSeconds}S`,
47
- text: hours > 0 ? `${String(hours)}:${pad(minutes)}:${pad(seconds)}` : `${String(minutes)}:${pad(seconds)}`
48
- };
49
- }
50
- if (elapsedSeconds < 60) {
51
- return {
52
- dateTime: `PT${elapsedSeconds}S`,
53
- text: `${String(elapsedSeconds)}s`
54
- };
55
- }
56
- const totalMinutes = Math.floor(elapsedSeconds / 60);
57
- if (totalMinutes < 60) {
58
- return {
59
- dateTime: `PT${elapsedSeconds}S`,
60
- text: `${String(totalMinutes)}m ${pad(elapsedSeconds % 60)}s`
61
- };
62
- }
63
- const representedSeconds = totalMinutes * 60;
64
- return {
65
- dateTime: `PT${representedSeconds}S`,
66
- text: `${String(Math.floor(totalMinutes / 60))}h ${pad(totalMinutes % 60)}m`
67
- };
68
- }
69
- function getMillisecondsUntilNextChange(now, startTime, elapsedMilliseconds, format) {
70
- if (now < startTime) {
71
- return Math.min(startTime - now + ONE_SECOND_MS, MAX_TIMEOUT_MS);
72
- }
73
- const precision = format === 'elapsed' && elapsedMilliseconds >= ONE_HOUR_SECONDS * ONE_SECOND_MS ? ONE_MINUTE_MS : ONE_SECOND_MS;
74
- return precision - elapsedMilliseconds % precision;
75
- }
76
- /**
77
- * Displays a standardized elapsed duration without scheduling React tick renders.
78
- *
79
- * Timer writes changing text and its ISO 8601 duration directly to the owned
80
- * `<time>` node. Use `elapsed` for compact duration text or `clock` for a
81
- * stopwatch-like reading.
82
- *
83
- * @example
84
- * ```
85
- * <Timer />
86
- * <Timer format="clock" />
87
- * ```
88
- */
89
- export function Timer({
90
- startTime,
91
- format = 'elapsed',
92
- type = 'supporting',
93
- size,
94
- color = 'secondary',
95
- weight,
96
- ref,
97
- xstyle,
98
- className,
99
- style,
100
- ...rest
101
- }) {
102
- const [mountTime] = useState(() => Date.now());
103
- const timerRef = useRef(null);
104
- const mergedRef = useMergedRefs(ref, timerRef);
105
- const resolvedFormat = resolveFormat(format);
106
- const initialPresentation = getPresentation(0, resolvedFormat);
107
- useEffect(() => {
108
- const resolvedStartTime = startTime !== undefined && Number.isFinite(startTime) ? startTime : mountTime;
109
- let timeoutID;
110
- let previousDateTime;
111
- let previousText;
112
- const tick = () => {
113
- const now = Date.now();
114
- const elapsedMilliseconds = getElapsedMilliseconds(now, resolvedStartTime);
115
- const presentation = getPresentation(elapsedMilliseconds, resolvedFormat);
116
- const node = timerRef.current;
117
- if (node != null) {
118
- if (presentation.text !== previousText) {
119
- node.textContent = presentation.text;
120
- previousText = presentation.text;
121
- }
122
- if (presentation.dateTime !== previousDateTime) {
123
- node.dateTime = presentation.dateTime;
124
- previousDateTime = presentation.dateTime;
125
- }
126
- }
127
- timeoutID = setTimeout(tick, getMillisecondsUntilNextChange(now, resolvedStartTime, elapsedMilliseconds, resolvedFormat));
128
- };
129
- tick();
130
- return () => {
131
- if (timeoutID !== undefined) {
132
- clearTimeout(timeoutID);
133
- }
134
- };
135
- }, [mountTime, resolvedFormat, startTime]);
136
- const timerProps = mergeProps(themeProps('timer'), {
137
- className,
138
- style
139
- });
140
- return /*#__PURE__*/_jsx(Text, {
141
- type: type,
142
- size: size,
143
- color: color,
144
- weight: weight,
145
- xstyle: xstyle,
146
- ...timerProps,
147
- children: /*#__PURE__*/_jsx("time", {
148
- ...rest,
149
- ref: mergedRef,
150
- dateTime: "PT0S",
151
- ...{
152
- className: "x1heor9g xt0psk2 xjb2p0i x1qlqyl8 x1j61x8r xss6m8b x1pd3egz x15bjb6t"
153
- },
154
- children: initialPresentation.text
155
- })
156
- });
157
- }
158
- Timer.displayName = 'Timer';