@shohojdhara/atomix 0.2.2 → 0.2.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.
Files changed (108) hide show
  1. package/dist/atomix.css +292 -529
  2. package/dist/atomix.min.css +5 -5
  3. package/dist/index.d.ts +623 -121
  4. package/dist/index.esm.js +11475 -6047
  5. package/dist/index.esm.js.map +1 -1
  6. package/dist/index.js +4698 -2755
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.min.js +1 -1
  9. package/dist/index.min.js.map +1 -1
  10. package/dist/themes/boomdevs.css +291 -528
  11. package/dist/themes/boomdevs.min.css +6 -6
  12. package/dist/themes/esrar.css +292 -529
  13. package/dist/themes/esrar.min.css +6 -6
  14. package/dist/themes/mashroom.css +286 -526
  15. package/dist/themes/mashroom.min.css +6 -6
  16. package/dist/themes/shaj-default.css +286 -526
  17. package/dist/themes/shaj-default.min.css +6 -6
  18. package/package.json +66 -15
  19. package/src/components/Accordion/Accordion.stories.tsx +137 -0
  20. package/src/components/Accordion/Accordion.tsx +33 -3
  21. package/src/components/AtomixGlass/AtomixGlass.stories.tsx +3011 -0
  22. package/src/components/AtomixGlass/AtomixGlass.test.tsx +199 -0
  23. package/src/components/AtomixGlass/AtomixGlass.tsx +1281 -0
  24. package/src/components/AtomixGlass/AtomixGlassComprehensivePreview.stories.tsx +1369 -0
  25. package/src/components/AtomixGlass/README.md +134 -0
  26. package/src/components/AtomixGlass/index.ts +10 -0
  27. package/src/components/AtomixGlass/shader-utils.ts +140 -0
  28. package/src/components/AtomixGlass/utils.ts +8 -0
  29. package/src/components/Badge/Badge.stories.tsx +169 -0
  30. package/src/components/Badge/Badge.tsx +27 -2
  31. package/src/components/Button/Button.stories.tsx +345 -0
  32. package/src/components/Button/Button.tsx +35 -3
  33. package/src/components/Button/README.md +216 -0
  34. package/src/components/Callout/Callout.stories.tsx +813 -78
  35. package/src/components/Callout/Callout.test.tsx +368 -0
  36. package/src/components/Callout/Callout.tsx +26 -7
  37. package/src/components/Callout/README.md +409 -0
  38. package/src/components/Card/Card.stories.tsx +140 -0
  39. package/src/components/Card/Card.tsx +19 -3
  40. package/src/components/DatePicker/DatePicker copy.tsx +551 -0
  41. package/src/components/DatePicker/DatePicker.stories.tsx +188 -0
  42. package/src/components/DatePicker/DatePicker.tsx +379 -332
  43. package/src/components/DatePicker/readme.md +110 -1
  44. package/src/components/DatePicker/types.ts +8 -0
  45. package/src/components/Dropdown/Dropdown.stories.tsx +145 -0
  46. package/src/components/Dropdown/Dropdown.tsx +34 -5
  47. package/src/components/Form/Checkbox.stories.tsx +101 -0
  48. package/src/components/Form/Checkbox.tsx +26 -2
  49. package/src/components/Form/Input.stories.tsx +124 -0
  50. package/src/components/Form/Input.tsx +36 -7
  51. package/src/components/Form/Radio.stories.tsx +139 -0
  52. package/src/components/Form/Radio.tsx +26 -2
  53. package/src/components/Form/Select.stories.tsx +110 -0
  54. package/src/components/Form/Select.tsx +26 -2
  55. package/src/components/Form/Textarea.stories.tsx +104 -0
  56. package/src/components/Form/Textarea.tsx +36 -7
  57. package/src/components/Hero/Hero.stories.tsx +54 -1
  58. package/src/components/Hero/Hero.tsx +70 -11
  59. package/src/components/Modal/Modal.stories.tsx +235 -0
  60. package/src/components/Modal/Modal.tsx +64 -35
  61. package/src/components/Pagination/Pagination.stories.tsx +101 -0
  62. package/src/components/Pagination/Pagination.tsx +25 -1
  63. package/src/components/Popover/Popover.stories.tsx +94 -0
  64. package/src/components/Popover/Popover.tsx +30 -4
  65. package/src/components/Rating/Rating.stories.tsx +112 -0
  66. package/src/components/Rating/Rating.tsx +25 -1
  67. package/src/components/Steps/Steps.stories.tsx +119 -0
  68. package/src/components/Steps/Steps.tsx +32 -1
  69. package/src/components/Tab/Tab.stories.tsx +88 -0
  70. package/src/components/Tab/Tab.tsx +32 -1
  71. package/src/components/Toggle/Toggle.stories.tsx +92 -0
  72. package/src/components/Toggle/Toggle.tsx +32 -1
  73. package/src/components/Tooltip/Tooltip.stories.tsx +131 -0
  74. package/src/components/Tooltip/Tooltip.tsx +43 -7
  75. package/src/components/VideoPlayer/VideoPlayer.stories.tsx +1002 -196
  76. package/src/components/VideoPlayer/VideoPlayer.tsx +161 -4
  77. package/src/components/index.ts +1 -0
  78. package/src/lib/composables/index.ts +4 -0
  79. package/src/lib/composables/useAtomixGlass.ts +71 -0
  80. package/src/lib/composables/useButton.ts +3 -1
  81. package/src/lib/composables/useCallout.ts +4 -1
  82. package/src/lib/composables/useGlassContainer.ts +168 -0
  83. package/src/lib/constants/components.ts +88 -0
  84. package/src/lib/types/components.ts +352 -0
  85. package/src/lib/utils/displacement-generator.ts +86 -0
  86. package/src/styles/01-settings/_settings.background.scss +8 -7
  87. package/src/styles/01-settings/_settings.callout.scss +7 -7
  88. package/src/styles/02-tools/_tools.animations.scss +19 -0
  89. package/src/styles/02-tools/_tools.background.scss +19 -17
  90. package/src/styles/02-tools/_tools.glass.scss +1 -0
  91. package/src/styles/03-generic/_generic.root.scss +3 -2
  92. package/src/styles/04-elements/_elements.body.scss +0 -18
  93. package/src/styles/06-components/_components.accordion.scss +16 -0
  94. package/src/styles/06-components/_components.atomix-glass.scss +0 -0
  95. package/src/styles/06-components/_components.badge.scss +34 -0
  96. package/src/styles/06-components/_components.button.scss +10 -0
  97. package/src/styles/06-components/_components.callout.scss +41 -2
  98. package/src/styles/06-components/_components.card.scss +17 -0
  99. package/src/styles/06-components/_components.chart.scss +1 -1
  100. package/src/styles/06-components/_components.datepicker.scss +18 -0
  101. package/src/styles/06-components/_components.dropdown.scss +7 -1
  102. package/src/styles/06-components/_components.hero.scss +1 -2
  103. package/src/styles/06-components/_components.input.scss +31 -1
  104. package/src/styles/06-components/_components.video-player.scss +48 -26
  105. package/src/styles/06-components/_index.scss +1 -0
  106. package/src/styles/99-utilities/_utilities.glass-fixes.scss +48 -0
  107. package/dist/themes/yabai.css +0 -15207
  108. package/dist/themes/yabai.min.css +0 -189
@@ -1,11 +1,12 @@
1
- import React from 'react';
1
+ import React, { forwardRef } from 'react';
2
2
  import { InputProps } from '../../lib/types/components';
3
3
  import { useInput } from '../../lib/composables/useInput';
4
+ import { AtomixGlass } from '../AtomixGlass/AtomixGlass';
4
5
 
5
6
  /**
6
7
  * Input - A component for text input fields
7
8
  */
8
- export const Input: React.FC<InputProps> = ({
9
+ export const Input = forwardRef<HTMLInputElement, InputProps>(({
9
10
  type = 'text',
10
11
  value,
11
12
  onChange,
@@ -32,7 +33,8 @@ export const Input: React.FC<InputProps> = ({
32
33
  step,
33
34
  ariaLabel,
34
35
  ariaDescribedBy,
35
- }) => {
36
+ glass,
37
+ }, ref) => {
36
38
  const { generateInputClass } = useInput({
37
39
  size,
38
40
  variant,
@@ -42,7 +44,7 @@ export const Input: React.FC<InputProps> = ({
42
44
  });
43
45
 
44
46
  const inputClass = generateInputClass({
45
- className,
47
+ className: `${className} ${glass ? 'c-input--glass' : ''}`.trim(),
46
48
  size,
47
49
  variant,
48
50
  disabled,
@@ -51,8 +53,12 @@ export const Input: React.FC<InputProps> = ({
51
53
  type,
52
54
  });
53
55
 
54
- return (
56
+ // Custom styles for glass effect
57
+ const glassStyles = glass ? {} : {};
58
+
59
+ const inputElement = (
55
60
  <input
61
+ ref={ref}
56
62
  type={type}
57
63
  className={inputClass}
58
64
  value={value}
@@ -76,12 +82,35 @@ export const Input: React.FC<InputProps> = ({
76
82
  aria-label={ariaLabel}
77
83
  aria-describedby={ariaDescribedBy}
78
84
  aria-invalid={invalid}
85
+ style={glass ? glassStyles : undefined}
79
86
  />
80
87
  );
81
- };
82
88
 
83
- export type { InputProps };
89
+ if (glass) {
90
+ // Default glass settings for inputs
91
+ const defaultGlassProps = {
92
+ displacementScale: 60,
93
+ blurAmount: 1,
94
+ saturation: 180,
95
+ aberrationIntensity: 0.2,
96
+ cornerRadius: 12,
97
+ mode: 'shader' as const,
98
+ };
99
+
100
+ const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
101
+
102
+ return (
103
+ <AtomixGlass {...glassProps}>
104
+ {inputElement}
105
+ </AtomixGlass>
106
+ );
107
+ }
108
+
109
+ return inputElement;
110
+ });
84
111
 
85
112
  Input.displayName = 'Input';
86
113
 
114
+ export type { InputProps };
115
+
87
116
  export default Input;
@@ -28,6 +28,10 @@ const meta = {
28
28
  control: 'boolean',
29
29
  description: 'Whether the radio button is valid',
30
30
  },
31
+ glass: {
32
+ control: 'boolean',
33
+ description: 'Enable glass morphism effect',
34
+ },
31
35
  },
32
36
  } satisfies Meta<typeof Radio>;
33
37
 
@@ -92,3 +96,138 @@ export const WithoutLabel: Story = {
92
96
  ariaLabel: 'Radio button without visible label',
93
97
  },
94
98
  };
99
+
100
+ // Glass variant
101
+ export const Glass: Story = {
102
+ args: {
103
+ label: 'Glass Radio',
104
+ name: 'glass',
105
+ value: 'glass',
106
+ glass: true,
107
+ },
108
+ render: (args) => (
109
+ <div
110
+ style={{
111
+ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
112
+ padding: '2rem',
113
+ borderRadius: '12px',
114
+ minHeight: '200px',
115
+ display: 'flex',
116
+ alignItems: 'center',
117
+ justifyContent: 'center',
118
+ }}
119
+ >
120
+ <Radio {...args} />
121
+ </div>
122
+ ),
123
+ };
124
+
125
+ // Glass with custom settings
126
+ export const GlassCustom: Story = {
127
+ args: {
128
+ label: 'Custom Glass Radio',
129
+ name: 'glassCustom',
130
+ value: 'glassCustom',
131
+ glass: {
132
+ displacementScale: 80,
133
+ blurAmount: 2,
134
+ saturation: 200,
135
+ aberrationIntensity: 0.8,
136
+ cornerRadius: 12,
137
+ },
138
+ },
139
+ render: (args) => (
140
+ <div
141
+ style={{
142
+ background: 'url(https://images.unsplash.com/photo-1506905925346-21bda4d32df4?ixlib=rb-4.0.3&auto=format&fit=crop&w=1000&q=80)',
143
+ backgroundSize: 'cover',
144
+ backgroundPosition: 'center',
145
+ padding: '2rem',
146
+ borderRadius: '12px',
147
+ minHeight: '200px',
148
+ display: 'flex',
149
+ alignItems: 'center',
150
+ justifyContent: 'center',
151
+ }}
152
+ >
153
+ <Radio {...args} />
154
+ </div>
155
+ ),
156
+ };
157
+
158
+ // Glass radio group
159
+ export const GlassGroup: Story = {
160
+ render: () => (
161
+ <div
162
+ style={{
163
+ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
164
+ padding: '2rem',
165
+ borderRadius: '12px',
166
+ minHeight: '300px',
167
+ display: 'flex',
168
+ alignItems: 'center',
169
+ justifyContent: 'center',
170
+ }}
171
+ >
172
+ <div>
173
+ <h3 style={{ color: 'white', marginBottom: '2rem', textAlign: 'center', textShadow: '0 2px 4px rgba(0,0,0,0.5)' }}>
174
+ Glass Radio Group
175
+ </h3>
176
+ <div className="u-d-flex u-flex-column u-gap-2">
177
+ <Radio label="Glass Option 1" name="glassGroup" value="option1" checked glass />
178
+ <Radio label="Glass Option 2" name="glassGroup" value="option2" glass />
179
+ <Radio label="Glass Option 3" name="glassGroup" value="option3" glass />
180
+ </div>
181
+ </div>
182
+ </div>
183
+ ),
184
+ };
185
+
186
+ // Glass states
187
+ export const GlassStates: Story = {
188
+ render: () => (
189
+ <div
190
+ style={{
191
+ background: 'linear-gradient(45deg, #ff6b6b, #4ecdc4, #45b7d1, #96ceb4, #feca57)',
192
+ backgroundSize: '400% 400%',
193
+ animation: 'gradient 15s ease infinite',
194
+ padding: '2rem',
195
+ borderRadius: '12px',
196
+ minHeight: '500px',
197
+ display: 'flex',
198
+ alignItems: 'center',
199
+ justifyContent: 'center',
200
+ }}
201
+ >
202
+ <style>
203
+ {`
204
+ @keyframes gradient {
205
+ 0% { background-position: 0% 50%; }
206
+ 50% { background-position: 100% 50%; }
207
+ 100% { background-position: 0% 50%; }
208
+ }
209
+ `}
210
+ </style>
211
+ <div>
212
+ <h3 style={{ color: 'white', marginBottom: '2rem', textAlign: 'center', textShadow: '0 2px 4px rgba(0,0,0,0.5)' }}>
213
+ Glass Radio States
214
+ </h3>
215
+ <div className="u-d-flex u-flex-column u-gap-2">
216
+ <Radio label="Glass Default" name="glassStates" value="default" glass />
217
+ <Radio label="Glass Checked" name="glassStates" value="checked" checked glass />
218
+ <Radio label="Glass Disabled" name="glassStates" value="disabled" disabled glass />
219
+ <Radio
220
+ label="Glass Disabled and Checked"
221
+ name="glassStates"
222
+ value="disabledChecked"
223
+ disabled
224
+ checked
225
+ glass
226
+ />
227
+ <Radio label="Glass Valid" name="glassStates" value="valid" valid checked glass />
228
+ <Radio label="Glass Invalid" name="glassStates" value="invalid" invalid glass />
229
+ </div>
230
+ </div>
231
+ </div>
232
+ ),
233
+ };
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { RadioProps } from '../../lib/types/components';
3
3
  import { useRadio } from '../../lib/composables/useRadio';
4
+ import { AtomixGlass } from '../AtomixGlass/AtomixGlass';
4
5
 
5
6
  /**
6
7
  * Radio - A component for radio button inputs
@@ -19,6 +20,7 @@ export const Radio: React.FC<RadioProps> = ({
19
20
  valid = false,
20
21
  ariaLabel,
21
22
  ariaDescribedBy,
23
+ glass,
22
24
  }) => {
23
25
  const { generateRadioClass } = useRadio({
24
26
  disabled,
@@ -27,13 +29,13 @@ export const Radio: React.FC<RadioProps> = ({
27
29
  });
28
30
 
29
31
  const radioClass = generateRadioClass({
30
- className,
32
+ className: `${className} ${glass ? 'c-radio--glass' : ''}`.trim(),
31
33
  disabled,
32
34
  invalid,
33
35
  valid,
34
36
  });
35
37
 
36
- return (
38
+ const radioContent = (
37
39
  <div className={radioClass}>
38
40
  <input
39
41
  type="radio"
@@ -56,6 +58,28 @@ export const Radio: React.FC<RadioProps> = ({
56
58
  )}
57
59
  </div>
58
60
  );
61
+
62
+ if (glass) {
63
+ // Default glass settings for radio buttons
64
+ const defaultGlassProps = {
65
+ displacementScale: 40,
66
+ blurAmount: 1,
67
+ saturation: 160,
68
+ aberrationIntensity: 0.3,
69
+ cornerRadius: 6,
70
+ mode: 'shader' as const,
71
+ };
72
+
73
+ const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
74
+
75
+ return (
76
+ <AtomixGlass {...glassProps}>
77
+ {radioContent}
78
+ </AtomixGlass>
79
+ );
80
+ }
81
+
82
+ return radioContent;
59
83
  };
60
84
 
61
85
  export type { RadioProps };
@@ -34,6 +34,10 @@ const meta = {
34
34
  control: 'boolean',
35
35
  description: 'Whether multiple options can be selected',
36
36
  },
37
+ glass: {
38
+ control: 'boolean',
39
+ description: 'Enable glass morphism effect',
40
+ },
37
41
  },
38
42
  } satisfies Meta<typeof Select>;
39
43
 
@@ -149,3 +153,109 @@ export const DisabledOptions: Story = {
149
153
  placeholder: 'Select a country',
150
154
  },
151
155
  };
156
+
157
+ // Glass variant
158
+ export const Glass: Story = {
159
+ args: {
160
+ options: countries,
161
+ placeholder: 'Glass Select',
162
+ glass: true,
163
+ },
164
+ render: (args) => (
165
+ <div
166
+ style={{
167
+ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
168
+ padding: '2rem',
169
+ borderRadius: '12px',
170
+ minHeight: '200px',
171
+ display: 'flex',
172
+ alignItems: 'center',
173
+ justifyContent: 'center',
174
+ }}
175
+ >
176
+ <div style={{ width: '100%', maxWidth: '300px' }}>
177
+ <Select {...args} />
178
+ </div>
179
+ </div>
180
+ ),
181
+ };
182
+
183
+ // Glass with custom settings
184
+ export const GlassCustom: Story = {
185
+ args: {
186
+ options: countries,
187
+ placeholder: 'Custom Glass Select',
188
+ glass: {
189
+ displacementScale: 80,
190
+ blurAmount: 2,
191
+ saturation: 200,
192
+ aberrationIntensity: 0.8,
193
+ cornerRadius: 12,
194
+ },
195
+ },
196
+ render: (args) => (
197
+ <div
198
+ style={{
199
+ background: 'url(https://images.unsplash.com/photo-1506905925346-21bda4d32df4?ixlib=rb-4.0.3&auto=format&fit=crop&w=1000&q=80)',
200
+ backgroundSize: 'cover',
201
+ backgroundPosition: 'center',
202
+ padding: '2rem',
203
+ borderRadius: '12px',
204
+ minHeight: '300px',
205
+ display: 'flex',
206
+ alignItems: 'center',
207
+ justifyContent: 'center',
208
+ }}
209
+ >
210
+ <div style={{ width: '100%', maxWidth: '300px' }}>
211
+ <h3 style={{ color: 'white', marginBottom: '1rem', textAlign: 'center', textShadow: '0 2px 4px rgba(0,0,0,0.5)' }}>
212
+ Custom Glass Select
213
+ </h3>
214
+ <Select {...args} />
215
+ </div>
216
+ </div>
217
+ ),
218
+ };
219
+
220
+ // Glass states
221
+ export const GlassStates: Story = {
222
+ args: {
223
+ options: countries,
224
+ },
225
+ render: (args) => (
226
+ <div
227
+ style={{
228
+ background: 'linear-gradient(45deg, #ff6b6b, #4ecdc4, #45b7d1, #96ceb4, #feca57)',
229
+ backgroundSize: '400% 400%',
230
+ animation: 'gradient 15s ease infinite',
231
+ padding: '2rem',
232
+ borderRadius: '12px',
233
+ minHeight: '400px',
234
+ display: 'flex',
235
+ alignItems: 'center',
236
+ justifyContent: 'center',
237
+ }}
238
+ >
239
+ <style>
240
+ {`
241
+ @keyframes gradient {
242
+ 0% { background-position: 0% 50%; }
243
+ 50% { background-position: 100% 50%; }
244
+ 100% { background-position: 0% 50%; }
245
+ }
246
+ `}
247
+ </style>
248
+ <div style={{ width: '100%', maxWidth: '300px' }}>
249
+ <h3 style={{ color: 'white', marginBottom: '2rem', textAlign: 'center', textShadow: '0 2px 4px rgba(0,0,0,0.5)' }}>
250
+ Glass Select States
251
+ </h3>
252
+ <div className="u-d-flex u-flex-column u-gap-3">
253
+ <Select options={args.options} placeholder="Glass Select" glass />
254
+ <Select options={args.options} placeholder="Glass Disabled" disabled glass />
255
+ <Select options={args.options} placeholder="Glass Valid" valid value="us" glass />
256
+ <Select options={args.options} placeholder="Glass Invalid" invalid glass />
257
+ </div>
258
+ </div>
259
+ </div>
260
+ ),
261
+ };
@@ -2,6 +2,7 @@ import React, { useRef, useEffect, useState } from 'react';
2
2
  import { SelectProps } from '../../lib/types/components';
3
3
  import { useSelect } from '../../lib/composables';
4
4
  import { SELECT } from '../../lib/constants/components';
5
+ import { AtomixGlass } from '../AtomixGlass/AtomixGlass';
5
6
 
6
7
  /**
7
8
  * Select - A component for dropdown selection
@@ -24,6 +25,7 @@ export const Select: React.FC<SelectProps> = ({
24
25
  multiple = false,
25
26
  ariaLabel,
26
27
  ariaDescribedBy,
28
+ glass,
27
29
  }) => {
28
30
  const { generateSelectClass } = useSelect({
29
31
  size,
@@ -33,7 +35,7 @@ export const Select: React.FC<SelectProps> = ({
33
35
  });
34
36
 
35
37
  const selectClass = generateSelectClass({
36
- className,
38
+ className: `${className} ${glass ? 'c-select--glass' : ''}`.trim(),
37
39
  size,
38
40
  disabled,
39
41
  invalid,
@@ -112,7 +114,7 @@ export const Select: React.FC<SelectProps> = ({
112
114
  }
113
115
  };
114
116
 
115
- return (
117
+ const selectContent = (
116
118
  <div
117
119
  className={`${selectClass} ${isOpen ? SELECT.CLASSES.IS_OPEN : ''}`}
118
120
  ref={dropdownRef}
@@ -182,6 +184,28 @@ export const Select: React.FC<SelectProps> = ({
182
184
  </div>
183
185
  </div>
184
186
  );
187
+
188
+ if (glass) {
189
+ // Default glass settings for select components
190
+ const defaultGlassProps = {
191
+ displacementScale: 60,
192
+ blurAmount: 1,
193
+ saturation: 180,
194
+ aberrationIntensity: 0.2,
195
+ cornerRadius: 12,
196
+ mode: 'shader' as const,
197
+ };
198
+
199
+ const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
200
+
201
+ return (
202
+ <AtomixGlass {...glassProps}>
203
+ {selectContent}
204
+ </AtomixGlass>
205
+ );
206
+ }
207
+
208
+ return selectContent;
185
209
  };
186
210
 
187
211
  export type { SelectProps };
@@ -46,6 +46,10 @@ const meta = {
46
46
  control: 'boolean',
47
47
  description: 'Whether the textarea is valid',
48
48
  },
49
+ glass: {
50
+ control: 'boolean',
51
+ description: 'Enable glass morphism effect',
52
+ },
49
53
  },
50
54
  } satisfies Meta<typeof Textarea>;
51
55
 
@@ -121,3 +125,103 @@ export const States: Story = {
121
125
  </div>
122
126
  ),
123
127
  };
128
+
129
+ // Glass Effect
130
+ export const Glass: Story = {
131
+ args: {
132
+ placeholder: 'Glass Textarea',
133
+ rows: 4,
134
+ glass: true,
135
+ },
136
+ render: (args) => (
137
+ <div
138
+ style={{
139
+ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
140
+ padding: '2rem',
141
+ borderRadius: '12px',
142
+ minHeight: '200px',
143
+ display: 'flex',
144
+ alignItems: 'center',
145
+ justifyContent: 'center',
146
+ }}
147
+ >
148
+ <Textarea {...args} />
149
+ </div>
150
+ ),
151
+ };
152
+
153
+ // Glass Variants
154
+ export const GlassVariants: Story = {
155
+ render: () => (
156
+ <div
157
+ style={{
158
+ background: 'linear-gradient(45deg, #f093fb 0%, #f5576c 100%)',
159
+ padding: '2rem',
160
+ borderRadius: '12px',
161
+ }}
162
+ >
163
+ <h3 style={{ color: 'white', marginBottom: '1rem', fontSize: '1.2rem' }}>
164
+ Glass Textarea Variants
165
+ </h3>
166
+ <div className="u-d-flex u-flex-column u-gap-3" style={{ width: '400px' }}>
167
+ <Textarea placeholder="Small Glass" size="sm" rows={3} glass />
168
+ <Textarea placeholder="Medium Glass" size="md" rows={3} glass />
169
+ <Textarea placeholder="Large Glass" size="lg" rows={3} glass />
170
+ <Textarea placeholder="Primary Glass" variant="primary" rows={3} glass />
171
+ <Textarea placeholder="Success Glass" variant="success" rows={3} glass />
172
+ <Textarea placeholder="Custom Glass" rows={4} glass={{
173
+ displacementScale: 80,
174
+ blurAmount: 2,
175
+ saturation: 200,
176
+ aberrationIntensity: 2,
177
+ cornerRadius: 12,
178
+ }} />
179
+ </div>
180
+ </div>
181
+ ),
182
+ };
183
+
184
+ // Glass Showcase
185
+ export const GlassShowcase: Story = {
186
+ render: () => (
187
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
188
+ {/* Basic Glass */}
189
+ <div
190
+ style={{
191
+ background: 'url(https://cdn.pixabay.com/photo/2021/11/13/08/50/athens-6790780_1280.jpg)',
192
+ backgroundSize: 'cover',
193
+ backgroundPosition: 'center',
194
+ padding: '2rem',
195
+ borderRadius: '12px',
196
+ }}
197
+ >
198
+ <h3 style={{ color: 'white', marginBottom: '1rem', fontSize: '1.2rem' }}>
199
+ Glass Textarea on Background
200
+ </h3>
201
+ <div className="u-d-flex u-flex-column u-gap-3" style={{ width: '400px' }}>
202
+ <Textarea placeholder="Write your message..." rows={4} glass />
203
+ <Textarea placeholder="Additional notes..." rows={3} glass />
204
+ </div>
205
+ </div>
206
+
207
+ {/* Different Glass Modes */}
208
+ <div
209
+ style={{
210
+ background: 'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)',
211
+ padding: '2rem',
212
+ borderRadius: '12px',
213
+ }}
214
+ >
215
+ <h3 style={{ color: 'white', marginBottom: '1rem', fontSize: '1.2rem' }}>
216
+ Glass Modes
217
+ </h3>
218
+ <div className="u-d-flex u-flex-column u-gap-3" style={{ width: '400px' }}>
219
+ <Textarea placeholder="Standard Mode" rows={3} glass={{ mode: 'standard' }} />
220
+ <Textarea placeholder="Polar Mode" rows={3} glass={{ mode: 'polar' }} />
221
+ <Textarea placeholder="Prominent Mode" rows={3} glass={{ mode: 'prominent' }} />
222
+ <Textarea placeholder="Shader Mode" rows={3} glass={{ mode: 'shader' }} />
223
+ </div>
224
+ </div>
225
+ </div>
226
+ ),
227
+ };
@@ -1,11 +1,12 @@
1
- import React from 'react';
1
+ import React, { forwardRef } from 'react';
2
2
  import { TextareaProps } from '../../lib/types/components';
3
3
  import { useTextarea } from '../../lib/composables/useTextarea';
4
+ import { AtomixGlass } from '../AtomixGlass/AtomixGlass';
4
5
 
5
6
  /**
6
7
  * Textarea - A component for multiline text input
7
8
  */
8
- export const Textarea: React.FC<TextareaProps> = ({
9
+ export const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>(({
9
10
  value,
10
11
  onChange,
11
12
  onBlur,
@@ -28,7 +29,8 @@ export const Textarea: React.FC<TextareaProps> = ({
28
29
  autoFocus = false,
29
30
  ariaLabel,
30
31
  ariaDescribedBy,
31
- }) => {
32
+ glass,
33
+ }, ref) => {
32
34
  const { generateTextareaClass } = useTextarea({
33
35
  size,
34
36
  variant,
@@ -38,7 +40,7 @@ export const Textarea: React.FC<TextareaProps> = ({
38
40
  });
39
41
 
40
42
  const textareaClass = generateTextareaClass({
41
- className,
43
+ className: `${className} ${glass ? 'c-input--glass' : ''}`.trim(),
42
44
  size,
43
45
  variant,
44
46
  disabled,
@@ -46,8 +48,12 @@ export const Textarea: React.FC<TextareaProps> = ({
46
48
  valid,
47
49
  });
48
50
 
49
- return (
51
+ // Custom styles for glass effect
52
+ const glassStyles = glass ? {} : {};
53
+
54
+ const textareaElement = (
50
55
  <textarea
56
+ ref={ref}
51
57
  className={textareaClass}
52
58
  value={value}
53
59
  onChange={onChange}
@@ -67,12 +73,35 @@ export const Textarea: React.FC<TextareaProps> = ({
67
73
  aria-label={ariaLabel}
68
74
  aria-describedby={ariaDescribedBy}
69
75
  aria-invalid={invalid}
76
+ style={glass ? glassStyles : undefined}
70
77
  />
71
78
  );
72
- };
73
79
 
74
- export type { TextareaProps };
80
+ if (glass) {
81
+ // Default glass settings for textareas
82
+ const defaultGlassProps = {
83
+ displacementScale: 60,
84
+ blurAmount: 1,
85
+ saturation: 180,
86
+ aberrationIntensity: 1,
87
+ cornerRadius: 8,
88
+ mode: 'shader' as const,
89
+ };
90
+
91
+ const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
92
+
93
+ return (
94
+ <AtomixGlass {...glassProps}>
95
+ {textareaElement}
96
+ </AtomixGlass>
97
+ );
98
+ }
99
+
100
+ return textareaElement;
101
+ });
75
102
 
76
103
  Textarea.displayName = 'Textarea';
77
104
 
105
+ export type { TextareaProps };
106
+
78
107
  export default Textarea;