Skip to content

Commit db77dd0

Browse files
authored
feat(genqa): add collapsible height option to the component (#4817)
[SVCC-4450](https://coveord.atlassian.net/browse/SVCC-4450) - Add new option `max-collapsed-height` to the genQA component. - Using relative dimensions to be consistent. - We keep `16 rem` as default value. - The accepted range of the height is from `9rem` to `32rem`, otherwise the default value is applied. - `--atomic-crga-collapsed-height` was already introduced in the css, just using it. (in `generated-answer.pcss`) **When `max-collapsed-height=9`** <img width="848" alt="Screenshot 2025-01-03 at 3 25 35 PM" src="https://github.com/user-attachments/assets/5d16a88d-d792-403d-8557-d9227cd08382" /> **When `max-collapsed-height=32`** <img width="479" alt="Screenshot 2025-01-03 at 3 26 43 PM" src="https://github.com/user-attachments/assets/90353dad-7b77-40c1-8033-a8d7d74a293a" /> **When `max-collapsed-height` outside of the range, back to default one** <img width="730" alt="Screenshot 2025-01-03 at 3 27 22 PM" src="https://github.com/user-attachments/assets/5f685e87-b62b-47f4-a1c2-667611603ef2" /> [SVCC-4450]: https://coveord.atlassian.net/browse/SVCC-4450?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
1 parent cf8bb89 commit db77dd0

File tree

4 files changed

+109
-11
lines changed

4 files changed

+109
-11
lines changed

packages/atomic-angular/projects/atomic-angular/src/lib/stencil-generated/components.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -984,14 +984,14 @@ export declare interface AtomicFormatUnit extends Components.AtomicFormatUnit {}
984984

985985

986986
@ProxyCmp({
987-
inputs: ['collapsible', 'tabsExcluded', 'tabsIncluded', 'withToggle']
987+
inputs: ['collapsible', 'maxCollapsedHeight', 'tabsExcluded', 'tabsIncluded', 'withToggle']
988988
})
989989
@Component({
990990
selector: 'atomic-generated-answer',
991991
changeDetection: ChangeDetectionStrategy.OnPush,
992992
template: '<ng-content></ng-content>',
993993
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
994-
inputs: ['collapsible', 'tabsExcluded', 'tabsIncluded', 'withToggle'],
994+
inputs: ['collapsible', 'maxCollapsedHeight', 'tabsExcluded', 'tabsIncluded', 'withToggle'],
995995
})
996996
export class AtomicGeneratedAnswer {
997997
protected el: HTMLElement;

packages/atomic/src/components.d.ts

+16
Original file line numberDiff line numberDiff line change
@@ -1087,6 +1087,10 @@ export namespace Components {
10871087
* @default false
10881088
*/
10891089
"collapsible"?: boolean;
1090+
/**
1091+
* The maximum height (in rem units) of the answer when collapsed.
1092+
*/
1093+
"maxCollapsedHeight": number;
10901094
/**
10911095
* The tabs on which this generated answer must not be displayed. This property should not be used at the same time as `tabs-included`. Set this property as a stringified JSON array, e.g., ```html <atomic-generated-answer tabs-excluded='["tabIDA", "tabIDB"]'></atomic-generated-answer> ``` If you don't set this property, the generated answer can be displayed on any tab. Otherwise, the generated answer won't be displayed on any of the specified tabs.
10921096
*/
@@ -1233,6 +1237,10 @@ export namespace Components {
12331237
* @default false
12341238
*/
12351239
"collapsible"?: boolean;
1240+
/**
1241+
* The maximum height (in rem units) of the answer when collapsed.
1242+
*/
1243+
"maxCollapsedHeight": number;
12361244
/**
12371245
* Whether to render a toggle button that lets the user hide or show the answer.
12381246
* @default false
@@ -7271,6 +7279,10 @@ declare namespace LocalJSX {
72717279
* @default false
72727280
*/
72737281
"collapsible"?: boolean;
7282+
/**
7283+
* The maximum height (in rem units) of the answer when collapsed.
7284+
*/
7285+
"maxCollapsedHeight"?: number;
72747286
/**
72757287
* The tabs on which this generated answer must not be displayed. This property should not be used at the same time as `tabs-included`. Set this property as a stringified JSON array, e.g., ```html <atomic-generated-answer tabs-excluded='["tabIDA", "tabIDB"]'></atomic-generated-answer> ``` If you don't set this property, the generated answer can be displayed on any tab. Otherwise, the generated answer won't be displayed on any of the specified tabs.
72767288
*/
@@ -7414,6 +7426,10 @@ declare namespace LocalJSX {
74147426
* @default false
74157427
*/
74167428
"collapsible"?: boolean;
7429+
/**
7430+
* The maximum height (in rem units) of the answer when collapsed.
7431+
*/
7432+
"maxCollapsedHeight"?: number;
74177433
/**
74187434
* Whether to render a toggle button that lets the user hide or show the answer.
74197435
* @default false

packages/atomic/src/components/insight/atomic-insight-generated-answer/atomic-insight-generated-answer.tsx

+45-4
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ export class AtomicInsightGeneratedAnswer
6868
public searchStatus!: InsightSearchStatus;
6969
private resizeObserver?: ResizeObserver;
7070

71+
private readonly DEFAULT_COLLAPSED_HEIGHT = 16;
72+
private readonly MAX_COLLAPSED_HEIGHT = 32;
73+
private readonly MIN_COLLAPSED_HEIGHT = 9;
74+
7175
@BindStateToController('generatedAnswer', {
7276
onUpdateCallbackMethod: 'onGeneratedAnswerStateUpdate',
7377
})
@@ -101,6 +105,12 @@ export class AtomicInsightGeneratedAnswer
101105
*/
102106
@Prop() collapsible?: boolean;
103107

108+
/**
109+
* The maximum height (in rem units) of the answer when collapsed.
110+
*
111+
*/
112+
@Prop() maxCollapsedHeight = this.DEFAULT_COLLAPSED_HEIGHT;
113+
104114
/**
105115
* @internal
106116
* The unique identifier of the answer configuration to use to generate the answer.
@@ -112,7 +122,6 @@ export class AtomicInsightGeneratedAnswer
112122

113123
private generatedAnswerCommon!: GeneratedAnswerCommon;
114124
private fullAnswerHeight?: number;
115-
private maxCollapsedHeight = 250;
116125

117126
public initialize() {
118127
this.generatedAnswerCommon = new GeneratedAnswerCommon({
@@ -213,10 +222,19 @@ export class AtomicInsightGeneratedAnswer
213222
}
214223

215224
private adaptAnswerHeight() {
216-
this.fullAnswerHeight = this.host?.shadowRoot
225+
const answerHeight = this.host?.shadowRoot
217226
?.querySelector('[part="generated-text"]')
218227
?.getBoundingClientRect().height;
219-
this.updateAnswerHeight();
228+
229+
if (answerHeight) {
230+
const rootFontSize = parseFloat(
231+
getComputedStyle(document.documentElement).fontSize
232+
);
233+
234+
this.fullAnswerHeight = answerHeight / rootFontSize;
235+
236+
this.updateAnswerHeight();
237+
}
220238
}
221239

222240
private getAnswerContainer() {
@@ -229,15 +247,38 @@ export class AtomicInsightGeneratedAnswer
229247
);
230248
}
231249

250+
private validateMaxCollapsedHeight(): number {
251+
const isValid =
252+
this.maxCollapsedHeight >= this.MIN_COLLAPSED_HEIGHT &&
253+
this.maxCollapsedHeight <= this.MAX_COLLAPSED_HEIGHT;
254+
255+
if (!isValid) {
256+
console.warn(
257+
`max-collapsed-height (${this.maxCollapsedHeight}rem) is out of the valid range (${this.MIN_COLLAPSED_HEIGHT}rem - ${this.MAX_COLLAPSED_HEIGHT}rem). Falling back to default value (${this.DEFAULT_COLLAPSED_HEIGHT}rem).`
258+
);
259+
}
260+
261+
return isValid ? this.maxCollapsedHeight : this.DEFAULT_COLLAPSED_HEIGHT;
262+
}
263+
264+
private setCSSVariable(variableName: string, value: string) {
265+
const container = this.getAnswerContainer();
266+
if (container) {
267+
(container as HTMLElement).style.setProperty(variableName, value);
268+
}
269+
}
270+
232271
private updateAnswerHeight() {
233272
const container = this.getAnswerContainer();
234273
const footer = this.getAnswerFooter();
274+
const maxHeight = this.validateMaxCollapsedHeight();
235275

236276
if (!container || !footer) {
237277
return;
238278
}
239279

240-
if (this.fullAnswerHeight! > this.maxCollapsedHeight) {
280+
if (this.fullAnswerHeight! > maxHeight) {
281+
this.setCSSVariable('--atomic-crga-collapsed-height', `${maxHeight}rem`);
241282
this.toggleClass(
242283
container,
243284
'answer-collapsed',

packages/atomic/src/components/search/atomic-generated-answer/atomic-generated-answer.tsx

+46-5
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ export class AtomicGeneratedAnswer implements InitializableComponent {
7171
public searchStatus!: SearchStatus;
7272
private resizeObserver?: ResizeObserver;
7373

74+
private readonly DEFAULT_COLLAPSED_HEIGHT = 16;
75+
private readonly MAX_COLLAPSED_HEIGHT = 32;
76+
private readonly MIN_COLLAPSED_HEIGHT = 9;
77+
7478
@BindStateToController('generatedAnswer', {
7579
onUpdateCallbackMethod: 'onGeneratedAnswerStateUpdate',
7680
})
@@ -110,6 +114,12 @@ export class AtomicGeneratedAnswer implements InitializableComponent {
110114
*/
111115
@Prop() collapsible?: boolean;
112116

117+
/**
118+
* The maximum height (in rem units) of the answer when collapsed.
119+
*
120+
*/
121+
@Prop() maxCollapsedHeight = this.DEFAULT_COLLAPSED_HEIGHT;
122+
113123
/**
114124
* @internal
115125
* The unique identifier of the answer configuration to use to generate the answer.
@@ -147,7 +157,6 @@ export class AtomicGeneratedAnswer implements InitializableComponent {
147157

148158
private generatedAnswerCommon!: GeneratedAnswerCommon;
149159
private fullAnswerHeight?: number;
150-
private maxCollapsedHeight = 250;
151160

152161
public initialize() {
153162
if (
@@ -257,10 +266,19 @@ export class AtomicGeneratedAnswer implements InitializableComponent {
257266
}
258267

259268
private adaptAnswerHeight() {
260-
this.fullAnswerHeight = this.host?.shadowRoot
269+
const answerHeight = this.host?.shadowRoot
261270
?.querySelector('[part="generated-text"]')
262271
?.getBoundingClientRect().height;
263-
this.updateAnswerHeight();
272+
273+
if (answerHeight) {
274+
const rootFontSize = parseFloat(
275+
getComputedStyle(document.documentElement).fontSize
276+
);
277+
278+
this.fullAnswerHeight = answerHeight / rootFontSize;
279+
280+
this.updateAnswerHeight();
281+
}
264282
}
265283

266284
private getAnswerContainer() {
@@ -273,15 +291,38 @@ export class AtomicGeneratedAnswer implements InitializableComponent {
273291
);
274292
}
275293

276-
private updateAnswerHeight() {
294+
private validateMaxCollapsedHeight(): number {
295+
const isValid =
296+
this.maxCollapsedHeight >= this.MIN_COLLAPSED_HEIGHT &&
297+
this.maxCollapsedHeight <= this.MAX_COLLAPSED_HEIGHT;
298+
299+
if (!isValid) {
300+
console.warn(
301+
`max-collapsed-height (${this.maxCollapsedHeight}rem) is out of the valid range (${this.MIN_COLLAPSED_HEIGHT}rem - ${this.MAX_COLLAPSED_HEIGHT}rem). Falling back to default value (${this.DEFAULT_COLLAPSED_HEIGHT}rem).`
302+
);
303+
}
304+
305+
return isValid ? this.maxCollapsedHeight : this.DEFAULT_COLLAPSED_HEIGHT;
306+
}
307+
308+
private setCSSVariable(variableName: string, value: string) {
277309
const container = this.getAnswerContainer();
310+
if (container) {
311+
(container as HTMLElement).style.setProperty(variableName, value);
312+
}
313+
}
314+
315+
private updateAnswerHeight() {
316+
const container = this.getAnswerContainer() as HTMLElement;
278317
const footer = this.getAnswerFooter();
318+
const maxHeight = this.validateMaxCollapsedHeight();
279319

280320
if (!container || !footer) {
281321
return;
282322
}
283323

284-
if (this.fullAnswerHeight! > this.maxCollapsedHeight) {
324+
if (this.fullAnswerHeight! > maxHeight) {
325+
this.setCSSVariable('--atomic-crga-collapsed-height', `${maxHeight}rem`);
285326
this.toggleClass(
286327
container,
287328
'answer-collapsed',

0 commit comments

Comments
 (0)