@shohojdhara/atomix 0.4.0 → 0.4.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 (66) hide show
  1. package/dist/atomix.css +9231 -9337
  2. package/dist/atomix.css.map +1 -1
  3. package/dist/atomix.min.css +2 -2
  4. package/dist/atomix.min.css.map +1 -1
  5. package/dist/charts.js +4 -5
  6. package/dist/charts.js.map +1 -1
  7. package/dist/core.d.ts +87 -10
  8. package/dist/core.js +673 -480
  9. package/dist/core.js.map +1 -1
  10. package/dist/forms.d.ts +15 -3
  11. package/dist/forms.js +530 -97
  12. package/dist/forms.js.map +1 -1
  13. package/dist/heavy.js +5 -6
  14. package/dist/heavy.js.map +1 -1
  15. package/dist/index.d.ts +495 -254
  16. package/dist/index.esm.js +1269 -723
  17. package/dist/index.esm.js.map +1 -1
  18. package/dist/index.js +1273 -723
  19. package/dist/index.js.map +1 -1
  20. package/dist/index.min.js +1 -1
  21. package/dist/index.min.js.map +1 -1
  22. package/package.json +2 -2
  23. package/scripts/atomix-cli.js +10 -1
  24. package/scripts/cli/__tests__/utils.test.js +6 -2
  25. package/scripts/cli/migration-tools.js +2 -2
  26. package/scripts/cli/theme-bridge.js +7 -9
  27. package/scripts/cli/utils.js +2 -1
  28. package/src/components/Accordion/Accordion.stories.tsx +40 -0
  29. package/src/components/Accordion/Accordion.tsx +174 -56
  30. package/src/components/Accordion/AccordionCompound.test.tsx +70 -0
  31. package/src/components/Breadcrumb/Breadcrumb.tsx +156 -50
  32. package/src/components/Breadcrumb/BreadcrumbCompound.test.tsx +84 -0
  33. package/src/components/Callout/Callout.stories.tsx +166 -1011
  34. package/src/components/Callout/Callout.tsx +196 -84
  35. package/src/components/Callout/CalloutCompound.test.tsx +72 -0
  36. package/src/components/Dropdown/Dropdown.tsx +133 -20
  37. package/src/components/Dropdown/DropdownCompound.test.tsx +64 -0
  38. package/src/components/EdgePanel/EdgePanel.tsx +164 -112
  39. package/src/components/EdgePanel/EdgePanelCompound.test.tsx +53 -0
  40. package/src/components/Form/Select.stories.tsx +23 -0
  41. package/src/components/Form/Select.test.tsx +99 -0
  42. package/src/components/Form/Select.tsx +144 -93
  43. package/src/components/Form/SelectOption.tsx +88 -0
  44. package/src/components/Hero/Hero.stories.tsx +37 -0
  45. package/src/components/Hero/Hero.test.tsx +142 -0
  46. package/src/components/Hero/Hero.tsx +142 -3
  47. package/src/components/List/List.test.tsx +62 -0
  48. package/src/components/List/List.tsx +16 -5
  49. package/src/components/List/ListItem.tsx +20 -0
  50. package/src/components/Modal/Modal.stories.tsx +65 -1
  51. package/src/components/Modal/Modal.tsx +115 -35
  52. package/src/components/Modal/ModalCompound.test.tsx +94 -0
  53. package/src/components/Steps/Steps.tsx +124 -21
  54. package/src/components/Steps/StepsCompound.test.tsx +81 -0
  55. package/src/components/Tabs/Tabs.tsx +197 -44
  56. package/src/components/Tabs/TabsCompound.test.tsx +64 -0
  57. package/src/lib/composables/index.ts +0 -4
  58. package/src/lib/composables/useAtomixGlass.ts +0 -15
  59. package/src/lib/theme/devtools/CLI.ts +2 -10
  60. package/src/lib/types/components.ts +8 -2
  61. package/src/lib/utils/__tests__/componentUtils.test.ts +57 -2
  62. package/src/lib/utils/__tests__/themeNaming.test.ts +117 -0
  63. package/src/lib/utils/themeNaming.ts +1 -1
  64. package/src/styles/02-tools/_tools.breakpoints.scss +1 -1
  65. package/src/styles/02-tools/_tools.utility-api.scss +6 -6
  66. package/src/styles/99-utilities/_utilities.text.scss +0 -1
@@ -1,15 +1,20 @@
1
- import React, { useRef, useEffect, useState, memo } from 'react';
2
- import { SelectProps } from '../../lib/types/components';
1
+ import React, { useRef, useEffect, useState, memo, useCallback } from 'react';
2
+ import { SelectProps, SelectOption as SelectOptionType } from '../../lib/types/components';
3
3
  import { useSelect } from '../../lib/composables';
4
4
  import { SELECT } from '../../lib/constants/components';
5
5
  import { AtomixGlass } from '../AtomixGlass/AtomixGlass';
6
+ import { SelectContext, SelectOption } from './SelectOption';
7
+
8
+ export type SelectComponent = React.FC<SelectProps> & {
9
+ Option: typeof SelectOption;
10
+ };
6
11
 
7
12
  /**
8
13
  * Select - A component for dropdown selection
9
14
  */
10
- export const Select: React.FC<SelectProps> = memo(
15
+ export const Select: SelectComponent = memo(
11
16
  ({
12
- options = [],
17
+ options,
13
18
  value,
14
19
  onChange,
15
20
  onBlur,
@@ -28,7 +33,8 @@ export const Select: React.FC<SelectProps> = memo(
28
33
  'aria-label': ariaLabel,
29
34
  'aria-describedby': ariaDescribedBy,
30
35
  glass,
31
- }) => {
36
+ children,
37
+ }: SelectProps) => {
32
38
  const { generateSelectClass } = useSelect({
33
39
  size,
34
40
  disabled,
@@ -51,17 +57,35 @@ export const Select: React.FC<SelectProps> = memo(
51
57
  const bodyRef = useRef<HTMLDivElement>(null);
52
58
  const nativeSelectRef = useRef<HTMLSelectElement>(null);
53
59
 
60
+ // State for registered options (Compound mode)
61
+ const [registeredOptions, setRegisteredOptions] = useState<SelectOptionType[]>([]);
62
+
63
+ const registerOption = useCallback((option: SelectOptionType) => {
64
+ setRegisteredOptions((prev) => {
65
+ if (prev.some(o => o.value === option.value)) return prev;
66
+ return [...prev, option];
67
+ });
68
+ }, []);
69
+
70
+ const unregisterOption = useCallback((value: string) => {
71
+ setRegisteredOptions((prev) => prev.filter(o => o.value !== value));
72
+ }, []);
73
+
74
+ // Determine active options
75
+ const hasOptionsProp = options && options.length > 0;
76
+ const activeOptions = hasOptionsProp ? options : registeredOptions;
77
+
54
78
  // Update selected label when value changes
55
79
  useEffect(() => {
56
80
  if (value) {
57
- const selectedOption = options.find(opt => opt.value === value);
81
+ const selectedOption = activeOptions.find(opt => opt.value === value);
58
82
  if (selectedOption) {
59
83
  setSelectedLabel(selectedOption.label);
60
84
  }
61
85
  } else {
62
86
  setSelectedLabel(placeholder);
63
87
  }
64
- }, [value, options, placeholder]);
88
+ }, [value, activeOptions, placeholder]);
65
89
 
66
90
  // Handle click outside to close dropdown
67
91
  useEffect(() => {
@@ -93,99 +117,125 @@ export const Select: React.FC<SelectProps> = memo(
93
117
  };
94
118
 
95
119
  // Handle item selection
96
- const handleItemClick = (option: { value: string; label: string }) => {
97
- setSelectedLabel(option.label);
98
- setIsOpen(false);
99
- if (bodyRef.current) {
100
- bodyRef.current.style.height = '0px';
101
- }
120
+ const handleItemClick = useCallback(
121
+ (option: { value: string; label: string }) => {
122
+ setSelectedLabel(option.label);
123
+ setIsOpen(false);
124
+ if (bodyRef.current) {
125
+ bodyRef.current.style.height = '0px';
126
+ }
102
127
 
103
- if (nativeSelectRef.current) {
104
- nativeSelectRef.current.value = option.value;
105
- }
128
+ if (nativeSelectRef.current) {
129
+ nativeSelectRef.current.value = option.value;
130
+ }
106
131
 
107
- if (onChange) {
108
- // Create a synthetic event
109
- const event = {
110
- target: {
111
- name,
112
- value: option.value,
113
- },
114
- } as React.ChangeEvent<HTMLSelectElement>;
115
- onChange(event);
116
- }
117
- };
132
+ if (onChange) {
133
+ // Create a synthetic event
134
+ const event = {
135
+ target: {
136
+ name,
137
+ value: option.value,
138
+ },
139
+ } as React.ChangeEvent<HTMLSelectElement>;
140
+ onChange(event);
141
+ }
142
+ },
143
+ [onChange, name]
144
+ );
145
+
146
+ const onSelect = useCallback(
147
+ (val: string, label: string) => {
148
+ handleItemClick({ value: val, label });
149
+ },
150
+ [handleItemClick]
151
+ );
152
+
153
+ const contextValue = React.useMemo(
154
+ () => ({
155
+ registerOption,
156
+ unregisterOption,
157
+ selectedValue: value,
158
+ onSelect,
159
+ }),
160
+ [registerOption, unregisterOption, value, onSelect]
161
+ );
118
162
 
119
163
  const selectContent = (
120
- <div
121
- className={`${selectClass} ${isOpen ? SELECT.CLASSES.IS_OPEN : ''}`}
122
- ref={dropdownRef}
123
- style={style}
124
- aria-expanded={isOpen}
125
- >
126
- {/* Native select for accessibility and form submission */}
127
- <select
128
- ref={nativeSelectRef}
129
- value={value}
130
- onChange={onChange}
131
- onBlur={onBlur}
132
- onFocus={onFocus}
133
- disabled={disabled}
134
- required={required}
135
- id={id}
136
- name={name}
137
- multiple={multiple}
138
- aria-label={ariaLabel}
139
- aria-describedby={ariaDescribedBy}
140
- aria-invalid={invalid}
141
- style={{ display: 'none' }}
164
+ <SelectContext.Provider value={contextValue}>
165
+ <div
166
+ className={`${selectClass} ${isOpen ? SELECT.CLASSES.IS_OPEN : ''}`}
167
+ ref={dropdownRef}
168
+ style={style}
169
+ aria-expanded={isOpen}
142
170
  >
143
- {placeholder && (
144
- <option value="" disabled>
145
- {placeholder}
146
- </option>
147
- )}
148
- {options.map(option => (
149
- <option key={option.value} value={option.value} disabled={option.disabled}>
150
- {option.label}
151
- </option>
152
- ))}
153
- </select>
154
-
155
- {/* Custom Select UI */}
156
- <div className={SELECT.CLASSES.SELECTED} onClick={handleToggle} aria-disabled={disabled}>
157
- {selectedLabel}
158
- </div>
171
+ {/* Native select for accessibility and form submission */}
172
+ <select
173
+ ref={nativeSelectRef}
174
+ value={value}
175
+ onChange={onChange}
176
+ onBlur={onBlur}
177
+ onFocus={onFocus}
178
+ disabled={disabled}
179
+ required={required}
180
+ id={id}
181
+ name={name}
182
+ multiple={multiple}
183
+ aria-label={ariaLabel}
184
+ aria-describedby={ariaDescribedBy}
185
+ aria-invalid={invalid}
186
+ style={{ display: 'none' }}
187
+ >
188
+ {placeholder && (
189
+ <option value="" disabled>
190
+ {placeholder}
191
+ </option>
192
+ )}
193
+ {activeOptions.map(option => (
194
+ <option key={option.value} value={option.value} disabled={option.disabled}>
195
+ {option.label}
196
+ </option>
197
+ ))}
198
+ </select>
199
+
200
+ {/* Custom Select UI */}
201
+ <div className={SELECT.CLASSES.SELECTED} onClick={handleToggle} aria-disabled={disabled}>
202
+ {selectedLabel}
203
+ </div>
204
+
205
+ <i className={`${SELECT.CLASSES.ICON_CARET} ${SELECT.CLASSES.TOGGLE_ICON}`} />
159
206
 
160
- <i className={`${SELECT.CLASSES.ICON_CARET} ${SELECT.CLASSES.TOGGLE_ICON}`} />
161
-
162
- <div className={SELECT.CLASSES.SELECT_BODY} ref={bodyRef} style={{ height: 0 }}>
163
- <div className={SELECT.CLASSES.SELECT_PANEL} ref={panelRef}>
164
- <ul className={SELECT.CLASSES.SELECT_ITEMS}>
165
- {options.map((option, index) => (
166
- <li
167
- key={option.value}
168
- className={SELECT.CLASSES.SELECT_ITEM}
169
- data-value={option.value}
170
- onClick={() => !option.disabled && handleItemClick(option)}
171
- >
172
- <label htmlFor={`SelectItem${index}`} className="c-checkbox">
173
- <input
174
- type="checkbox"
175
- id={`SelectItem${index}`}
176
- className="c-checkbox__input c-select__item-input"
177
- checked={value === option.value}
178
- readOnly
179
- disabled={option.disabled}
180
- />
181
- <div className="c-select__item-label">{option.label}</div>
182
- </label>
183
- </li>
184
- ))}
185
- </ul>
207
+ <div className={SELECT.CLASSES.SELECT_BODY} ref={bodyRef} style={{ height: 0 }}>
208
+ <div className={SELECT.CLASSES.SELECT_PANEL} ref={panelRef}>
209
+ <ul className={SELECT.CLASSES.SELECT_ITEMS}>
210
+ {hasOptionsProp ? (
211
+ options.map((option, index) => (
212
+ <li
213
+ key={option.value}
214
+ className={SELECT.CLASSES.SELECT_ITEM}
215
+ data-value={option.value}
216
+ onClick={() => !option.disabled && handleItemClick(option)}
217
+ >
218
+ <label htmlFor={`SelectItem${index}`} className="c-checkbox">
219
+ <input
220
+ type="checkbox"
221
+ id={`SelectItem${index}`}
222
+ className="c-checkbox__input c-select__item-input"
223
+ checked={value === option.value}
224
+ readOnly
225
+ disabled={option.disabled}
226
+ />
227
+ <div className="c-select__item-label">{option.label}</div>
228
+ </label>
229
+ </li>
230
+ ))
231
+ ) : (
232
+ children
233
+ )}
234
+ </ul>
235
+ </div>
186
236
  </div>
187
237
  </div>
188
- </div>
238
+ </SelectContext.Provider>
189
239
  );
190
240
 
191
241
  if (glass) {
@@ -206,10 +256,11 @@ export const Select: React.FC<SelectProps> = memo(
206
256
 
207
257
  return selectContent;
208
258
  }
209
- );
259
+ ) as unknown as SelectComponent;
210
260
 
211
261
  export type { SelectProps };
212
262
 
213
263
  Select.displayName = 'Select';
264
+ Select.Option = SelectOption;
214
265
 
215
266
  export default Select;
@@ -0,0 +1,88 @@
1
+ import React, { createContext, useContext, useEffect, memo, ReactNode } from 'react';
2
+ import { SelectOption as SelectOptionType } from '../../lib/types/components';
3
+ import { SELECT } from '../../lib/constants/components';
4
+
5
+ // Context for managing options registration and selection
6
+ export interface SelectContextType {
7
+ registerOption: (option: SelectOptionType) => void;
8
+ unregisterOption: (value: string) => void;
9
+ selectedValue?: string | string[];
10
+ onSelect: (value: string, label: string) => void;
11
+ }
12
+
13
+ export const SelectContext = createContext<SelectContextType | null>(null);
14
+
15
+ export interface SelectOptionProps {
16
+ value: string;
17
+ children?: ReactNode;
18
+ disabled?: boolean;
19
+ className?: string;
20
+ style?: React.CSSProperties;
21
+ }
22
+
23
+ export const SelectOption: React.FC<SelectOptionProps> = memo(
24
+ ({ value, children, disabled = false, className = '', style }) => {
25
+ const context = useContext(SelectContext);
26
+
27
+ // We assume children is the label if it's a string, or we need a way to get label.
28
+ // For simplicity, we use children as label for registration if it's a string.
29
+ const label = typeof children === 'string' ? children : value;
30
+
31
+ useEffect(() => {
32
+ if (context) {
33
+ context.registerOption({ value, label, disabled });
34
+ return () => {
35
+ context.unregisterOption(value);
36
+ };
37
+ }
38
+ return undefined;
39
+ }, [context, value, label, disabled]);
40
+
41
+ if (!context) {
42
+ console.warn('SelectOption must be used within a Select component');
43
+ return null;
44
+ }
45
+
46
+ const { selectedValue, onSelect } = context;
47
+
48
+ const isSelected = Array.isArray(selectedValue)
49
+ ? selectedValue.includes(value)
50
+ : selectedValue === value;
51
+
52
+ const handleClick = (e: React.MouseEvent) => {
53
+ e.preventDefault();
54
+ e.stopPropagation();
55
+ if (!disabled) {
56
+ onSelect(value, label);
57
+ }
58
+ };
59
+
60
+ return (
61
+ <li
62
+ className={`${SELECT.CLASSES.SELECT_ITEM} ${className}`.trim()}
63
+ data-value={value}
64
+ onClick={handleClick}
65
+ style={style}
66
+ role="option"
67
+ aria-selected={isSelected}
68
+ aria-disabled={disabled}
69
+ >
70
+ <label className="c-checkbox" style={{ pointerEvents: 'none' }}>
71
+ <input
72
+ type="checkbox"
73
+ className="c-checkbox__input c-select__item-input"
74
+ checked={isSelected}
75
+ readOnly
76
+ disabled={disabled}
77
+ tabIndex={-1}
78
+ />
79
+ <div className="c-select__item-label">{children}</div>
80
+ </label>
81
+ </li>
82
+ );
83
+ }
84
+ );
85
+
86
+ SelectOption.displayName = 'SelectOption';
87
+
88
+ export default SelectOption;
@@ -279,6 +279,43 @@ export const BasicUsage: Story = {
279
279
  },
280
280
  };
281
281
 
282
+ /**
283
+ * Hero using Compound Component Pattern
284
+ */
285
+ export const CompoundUsage: Story = {
286
+ render: (args) => (
287
+ <Hero {...args}>
288
+ <Hero.Content>
289
+ <Hero.Title level="h1">Compound Component Pattern</Hero.Title>
290
+ <Hero.Subtitle>Fully Customizable Structure</Hero.Subtitle>
291
+ <Hero.Text>
292
+ This example demonstrates the new Compound Component pattern, allowing full control over the internal structure of the Hero component.
293
+ </Hero.Text>
294
+ <Hero.Actions>
295
+ <Button variant="primary" className="u-mr-3">
296
+ Get Started
297
+ </Button>
298
+ <Button variant="outline">Learn More</Button>
299
+ </Hero.Actions>
300
+ </Hero.Content>
301
+ </Hero>
302
+ ),
303
+ args: {
304
+ fullViewportHeight: true,
305
+ alignment: 'center',
306
+ backgroundImageSrc: 'https://picsum.photos/id/1015/1920/1080',
307
+ title: '', // Ignored but kept for types
308
+ showOverlay: true,
309
+ },
310
+ parameters: {
311
+ docs: {
312
+ description: {
313
+ story: 'Using the Compound Component pattern for maximum flexibility.',
314
+ },
315
+ },
316
+ },
317
+ };
318
+
282
319
  export const WithImage: Story = {
283
320
  args: {
284
321
  title: 'Beautiful Interfaces',
@@ -0,0 +1,142 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { describe, it, expect, vi } from 'vitest';
4
+ import Hero from './Hero';
5
+
6
+ // Mock AtomixGlass component
7
+ vi.mock('../AtomixGlass/AtomixGlass', () => ({
8
+ AtomixGlass: ({ children, className }: any) => (
9
+ <div data-testid="atomix-glass" className={className}>
10
+ {children}
11
+ </div>
12
+ ),
13
+ }));
14
+
15
+ describe('Hero Component', () => {
16
+ describe('Monolithic Usage', () => {
17
+ it('renders title and subtitle correctly', () => {
18
+ render(<Hero title="Test Title" subtitle="Test Subtitle" />);
19
+
20
+ expect(screen.getByText('Test Title')).toBeInTheDocument();
21
+ expect(screen.getByText('Test Subtitle')).toBeInTheDocument();
22
+ });
23
+
24
+ it('renders text content correctly', () => {
25
+ render(<Hero title="Title" text="Test Description" />);
26
+
27
+ expect(screen.getByText('Test Description')).toBeInTheDocument();
28
+ });
29
+
30
+ it('renders background image correctly', () => {
31
+ const bgSrc = 'test-bg.jpg';
32
+ render(<Hero title="Title" backgroundImageSrc={bgSrc} />);
33
+
34
+ const bgImage = screen.getByAltText('Background');
35
+ expect(bgImage).toBeInTheDocument();
36
+ expect(bgImage).toHaveAttribute('src', bgSrc);
37
+ });
38
+
39
+ it('renders foreground image correctly', () => {
40
+ const imgSrc = 'test-img.jpg';
41
+ render(<Hero title="Title" imageSrc={imgSrc} imageAlt="Foreground Image" />);
42
+
43
+ const image = screen.getByAltText('Foreground Image');
44
+ expect(image).toBeInTheDocument();
45
+ expect(image).toHaveAttribute('src', imgSrc);
46
+ });
47
+
48
+ it('renders actions correctly', () => {
49
+ render(
50
+ <Hero
51
+ title="Title"
52
+ actions={<button>Click Me</button>}
53
+ />
54
+ );
55
+
56
+ expect(screen.getByText('Click Me')).toBeInTheDocument();
57
+ });
58
+
59
+ it('renders children correctly', () => {
60
+ render(
61
+ <Hero title="Title">
62
+ <div data-testid="child-content">Child Content</div>
63
+ </Hero>
64
+ );
65
+
66
+ expect(screen.getByTestId('child-content')).toBeInTheDocument();
67
+ });
68
+ });
69
+
70
+ describe('Compound Component Usage', () => {
71
+ it('renders Hero.Title, Hero.Subtitle, Hero.Text correctly', () => {
72
+ render(
73
+ <Hero title="">
74
+ <Hero.Content>
75
+ <Hero.Title>Compound Title</Hero.Title>
76
+ <Hero.Subtitle>Compound Subtitle</Hero.Subtitle>
77
+ <Hero.Text>Compound Text</Hero.Text>
78
+ </Hero.Content>
79
+ </Hero>
80
+ );
81
+
82
+ expect(screen.getByText('Compound Title')).toBeInTheDocument();
83
+ expect(screen.getByText('Compound Title').tagName).toBe('H1');
84
+ expect(screen.getByText('Compound Subtitle')).toBeInTheDocument();
85
+ expect(screen.getByText('Compound Text')).toBeInTheDocument();
86
+ });
87
+
88
+ it('renders Hero.Actions correctly', () => {
89
+ render(
90
+ <Hero title="">
91
+ <Hero.Content>
92
+ <Hero.Actions>
93
+ <button>Action</button>
94
+ </Hero.Actions>
95
+ </Hero.Content>
96
+ </Hero>
97
+ );
98
+
99
+ expect(screen.getByText('Action')).toBeInTheDocument();
100
+ });
101
+
102
+ it('renders Hero.Image correctly', () => {
103
+ render(
104
+ <Hero title="">
105
+ <Hero.Image src="compound-img.jpg" alt="Compound Image" />
106
+ </Hero>
107
+ );
108
+
109
+ const img = screen.getByAltText('Compound Image');
110
+ expect(img).toBeInTheDocument();
111
+ expect(img).toHaveAttribute('src', 'compound-img.jpg');
112
+ });
113
+
114
+ it('renders Hero.Background via backgroundElement prop', () => {
115
+ render(
116
+ <Hero
117
+ title="Title"
118
+ backgroundElement={<Hero.Background src="bg.jpg" data-testid="custom-bg" />}
119
+ />
120
+ );
121
+
122
+ const bg = screen.getByTestId('custom-bg');
123
+ expect(bg).toBeInTheDocument();
124
+ // Verify it renders the image inside
125
+ const img = screen.getByAltText('Background');
126
+ expect(img).toHaveAttribute('src', 'bg.jpg');
127
+ });
128
+
129
+ it('Hero.Content supports glass prop', () => {
130
+ render(
131
+ <Hero title="">
132
+ <Hero.Content glass>
133
+ Glass Content
134
+ </Hero.Content>
135
+ </Hero>
136
+ );
137
+
138
+ expect(screen.getByTestId('atomix-glass')).toBeInTheDocument();
139
+ expect(screen.getByText('Glass Content')).toBeInTheDocument();
140
+ });
141
+ });
142
+ });