igniteui-cli 14.10.0-alpha.3 → 14.10.0-alpha.4

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 (17) hide show
  1. package/package.json +4 -4
  2. package/templates/react/igr-ts/projects/_base/files/__dot__claude/skills/igniteui-react-components/SKILL.md +161 -0
  3. package/templates/react/igr-ts/projects/_base/files/__dot__claude/skills/igniteui-react-components/reference/CHARTS-GRIDS.md +127 -0
  4. package/templates/react/igr-ts/projects/_base/files/__dot__claude/skills/igniteui-react-components/reference/COMPONENT-CATALOGUE.md +301 -0
  5. package/templates/react/igr-ts/projects/_base/files/__dot__claude/skills/igniteui-react-components/reference/EVENT-HANDLING.md +70 -0
  6. package/templates/react/igr-ts/projects/_base/files/__dot__claude/skills/igniteui-react-components/reference/INSTALLATION.md +139 -0
  7. package/templates/react/igr-ts/projects/_base/files/__dot__claude/skills/igniteui-react-components/reference/JSX-PATTERNS.md +187 -0
  8. package/templates/react/igr-ts/projects/_base/files/__dot__claude/skills/igniteui-react-components/reference/REFS-FORMS.md +229 -0
  9. package/templates/react/igr-ts/projects/_base/files/__dot__claude/skills/igniteui-react-components/reference/REVEAL-SDK.md +198 -0
  10. package/templates/react/igr-ts/projects/_base/files/__dot__claude/skills/igniteui-react-components/reference/TROUBLESHOOTING.md +147 -0
  11. package/templates/react/igr-ts/projects/_base/files/__dot__claude/skills/igniteui-react-customize-theme/SKILL.md +182 -0
  12. package/templates/react/igr-ts/projects/_base/files/__dot__claude/skills/igniteui-react-customize-theme/reference/CSS-THEMING.md +265 -0
  13. package/templates/react/igr-ts/projects/_base/files/__dot__claude/skills/igniteui-react-customize-theme/reference/MCP-SERVER.md +75 -0
  14. package/templates/react/igr-ts/projects/_base/files/__dot__claude/skills/igniteui-react-customize-theme/reference/REVEAL-THEME.md +86 -0
  15. package/templates/react/igr-ts/projects/_base/files/__dot__claude/skills/igniteui-react-customize-theme/reference/SASS-THEMING.md +125 -0
  16. package/templates/react/igr-ts/projects/_base/files/__dot__claude/skills/igniteui-react-customize-theme/reference/TROUBLESHOOTING.md +35 -0
  17. package/templates/react/igr-ts/projects/_base/files/__dot__claude/skills/igniteui-react-optimize-bundle-size/SKILL.md +439 -0
@@ -0,0 +1,70 @@
1
+ # Event Handling
2
+
3
+ ## How Events Work
4
+
5
+ Ignite UI React wrappers map web component custom events to React-style `onXxx` callback props. The event name is converted from the web component event name to a camelCase `on`-prefixed prop.
6
+
7
+ ```tsx
8
+ import { IgrButton, IgrInput, IgrCheckbox } from 'igniteui-react';
9
+
10
+ function MyForm() {
11
+ const handleClick = (event: CustomEvent) => {
12
+ console.log('Button clicked');
13
+ };
14
+
15
+ const handleInput = (event: CustomEvent) => {
16
+ // event.target is the underlying web component element (e.g., igc-input)
17
+ console.log('Input value:', (event.target as any).value);
18
+ };
19
+
20
+ const handleChange = (event: CustomEvent) => {
21
+ console.log('Checkbox changed:', event.detail);
22
+ };
23
+
24
+ return (
25
+ <>
26
+ <IgrButton onClick={handleClick}>
27
+ <span>Submit</span>
28
+ </IgrButton>
29
+ <IgrInput label="Name" onInput={handleInput} />
30
+ <IgrCheckbox onChange={handleChange}>Accept terms</IgrCheckbox>
31
+ </>
32
+ );
33
+ }
34
+ ```
35
+
36
+ ## Common Event Props
37
+
38
+ | Component | Event Prop | Fires When |
39
+ |---|---|---|
40
+ | `IgrButton` | `onClick` | Button is clicked |
41
+ | `IgrInput` | `onInput` | Value changes (each keystroke) |
42
+ | `IgrInput` | `onChange` | Value committed (blur / Enter) |
43
+ | `IgrCheckbox` | `onChange` | Checked state changes |
44
+ | `IgrSwitch` | `onChange` | Toggle state changes |
45
+ | `IgrSelect` | `onChange` | Selection changes |
46
+ | `IgrCombo` | `onChange` | Selection changes |
47
+ | `IgrSlider` | `onInput` | Slider value changes (live) |
48
+ | `IgrSlider` | `onChange` | Slider value committed |
49
+ | `IgrDialog` | `onClosing` | Dialog is about to close |
50
+ | `IgrDialog` | `onClosed` | Dialog has closed |
51
+ | `IgrTabs` | `onChange` | Active tab changes |
52
+ | `IgrCalendar` | `onChange` | Selected date changes |
53
+ | `IgrDatepicker` | `onChange` | Selected date changes |
54
+
55
+ ## TypeScript Event Types
56
+
57
+ When using TypeScript, event handlers receive the underlying `CustomEvent`:
58
+
59
+ ```tsx
60
+ import { IgrInput } from 'igniteui-react';
61
+
62
+ function SearchBar() {
63
+ const handleInput = (e: CustomEvent) => {
64
+ const value = (e.target as HTMLInputElement).value;
65
+ console.log('Search:', value);
66
+ };
67
+
68
+ return <IgrInput label="Search" onInput={handleInput} />;
69
+ }
70
+ ```
@@ -0,0 +1,139 @@
1
+ # Installation & Setup
2
+
3
+ ## Install the Package
4
+
5
+ ```bash
6
+ # Core UI components (MIT)
7
+ npm install igniteui-react
8
+
9
+ # If you need the lightweight grid (MIT)
10
+ # Requires BOTH packages - igniteui-react and igniteui-grid-lite
11
+ npm install igniteui-react igniteui-grid-lite
12
+
13
+ # If you need advanced grids (commercial)
14
+ npm install igniteui-react-grids
15
+
16
+ # If you need charts (commercial)
17
+ npm install igniteui-react-charts
18
+
19
+ # If you need gauges (commercial)
20
+ npm install igniteui-react-gauges
21
+
22
+ # If you need maps (commercial)
23
+ npm install igniteui-react-maps
24
+ ```
25
+
26
+ ## Peer Dependencies
27
+
28
+ `igniteui-react` requires `react` and `react-dom` (v18+ or v19+). These are typically already in your project:
29
+
30
+ ```bash
31
+ npm install react react-dom
32
+ ```
33
+
34
+ ## Import a Theme (REQUIRED)
35
+
36
+ > **CRITICAL:** Components will render without styles, with broken icons and missing visuals if the theme CSS is not imported. **Always import the theme CSS before using any Ignite UI component.**
37
+
38
+ Import one theme CSS file in your entry point (`main.tsx`, `index.tsx`, or `App.tsx`). The theme CSS must be imported **in every file that uses Ignite UI components** if your framework does not have a single global entry point (e.g., Next.js — see below).
39
+
40
+ ```tsx
41
+ // main.tsx or index.tsx
42
+ import 'igniteui-webcomponents/themes/light/bootstrap.css';
43
+ ```
44
+
45
+ Available themes:
46
+
47
+ | Import | Theme |
48
+ |---|---|
49
+ | `igniteui-webcomponents/themes/light/bootstrap.css` | Bootstrap Light |
50
+ | `igniteui-webcomponents/themes/dark/bootstrap.css` | Bootstrap Dark |
51
+ | `igniteui-webcomponents/themes/light/material.css` | Material Light |
52
+ | `igniteui-webcomponents/themes/dark/material.css` | Material Dark |
53
+ | `igniteui-webcomponents/themes/light/fluent.css` | Fluent Light |
54
+ | `igniteui-webcomponents/themes/dark/fluent.css` | Fluent Dark |
55
+ | `igniteui-webcomponents/themes/light/indigo.css` | Indigo Light |
56
+ | `igniteui-webcomponents/themes/dark/indigo.css` | Indigo Dark |
57
+
58
+ Grid theme CSS files follow the same pattern under `igniteui-react-grids/grids/themes/`.
59
+
60
+ **For grids**, you **must also** import the grid theme CSS. Without it, the grid will be missing styles and icons will show as placeholders:
61
+
62
+ ```tsx
63
+ import 'igniteui-webcomponents/themes/light/bootstrap.css';
64
+ import 'igniteui-react-grids/grids/themes/light/bootstrap.css';
65
+ ```
66
+
67
+ ## Next.js Setup
68
+
69
+ In Next.js, there is no single `main.tsx` entry point. Import the theme CSS **in each client component file** that uses Ignite UI components, or in a shared layout component:
70
+
71
+ ```tsx
72
+ // app/components/DataTable.tsx
73
+ 'use client';
74
+
75
+ import 'igniteui-webcomponents/themes/light/bootstrap.css';
76
+ import 'igniteui-react-grids/grids/themes/light/bootstrap.css';
77
+
78
+ import { IgrGrid, IgrColumn, IgrPaginator } from 'igniteui-react-grids';
79
+
80
+ export default function DataTable({ data }: { data: any[] }) {
81
+ return (
82
+ <IgrGrid data={data} autoGenerate={false}>
83
+ <IgrColumn field="name" header="Name" />
84
+ <IgrColumn field="email" header="Email" />
85
+ <IgrPaginator perPage={10} />
86
+ </IgrGrid>
87
+ );
88
+ }
89
+ ```
90
+
91
+ Alternatively, import themes once in a root layout:
92
+
93
+ ```tsx
94
+ // app/layout.tsx
95
+ import 'igniteui-webcomponents/themes/light/bootstrap.css';
96
+ import 'igniteui-react-grids/grids/themes/light/bootstrap.css';
97
+
98
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
99
+ return (
100
+ <html lang="en">
101
+ <body>{children}</body>
102
+ </html>
103
+ );
104
+ }
105
+ ```
106
+
107
+ ## Minimal App Example (Vite / CRA)
108
+
109
+ ```tsx
110
+ // main.tsx
111
+ import React from 'react';
112
+ import ReactDOM from 'react-dom/client';
113
+ import 'igniteui-webcomponents/themes/light/bootstrap.css';
114
+ import App from './App';
115
+
116
+ ReactDOM.createRoot(document.getElementById('root')!).render(
117
+ <React.StrictMode>
118
+ <App />
119
+ </React.StrictMode>
120
+ );
121
+ ```
122
+
123
+ ```tsx
124
+ // App.tsx
125
+ import { IgrButton, IgrInput } from 'igniteui-react';
126
+
127
+ function App() {
128
+ return (
129
+ <div>
130
+ <IgrInput label="Name" />
131
+ <IgrButton><span>Submit</span></IgrButton>
132
+ </div>
133
+ );
134
+ }
135
+
136
+ export default App;
137
+ ```
138
+
139
+ > **No `defineComponents()` needed.** React wrappers auto-register. See [CHARTS-GRIDS.md](./reference/CHARTS-GRIDS.md) for exceptions (charts, gauges, maps).
@@ -0,0 +1,187 @@
1
+ # JSX Usage Patterns
2
+
3
+ ## Props vs HTML Attributes
4
+
5
+ Ignite UI React components accept props just like any React component. Use JSX expression syntax for dynamic values:
6
+
7
+ ```tsx
8
+ // ✅ Correct — JSX expression
9
+ <IgrInput label="Email" placeholder="you@example.com" type="email" />
10
+ <IgrSlider value={50} min={0} max={100} />
11
+ <IgrButton disabled={isLoading}>Submit</IgrButton>
12
+
13
+ // ❌ Wrong — string for numeric/boolean values
14
+ <IgrSlider value="50" />
15
+ ```
16
+
17
+ ## Children vs Slots
18
+
19
+ Ignite UI components use the web component **slot** mechanism under the hood. In JSX, pass children to the default slot and use the `slot` attribute to target named slots:
20
+
21
+ ```tsx
22
+ <IgrButton>
23
+ {/* Default slot — button label */}
24
+ <span>Click Me</span>
25
+ </IgrButton>
26
+
27
+ <IgrCard>
28
+ <IgrCardHeader>
29
+ <h3 slot="title">Card Title</h3>
30
+ <p slot="subtitle">Card subtitle</p>
31
+ </IgrCardHeader>
32
+ <IgrCardContent>
33
+ <p>Default slot content inside the card body.</p>
34
+ </IgrCardContent>
35
+ <IgrCardActions>
36
+ <IgrButton slot="start">Cancel</IgrButton>
37
+ <IgrButton slot="end">Confirm</IgrButton>
38
+ </IgrCardActions>
39
+ </IgrCard>
40
+
41
+ <IgrNavDrawerItem>
42
+ <span slot="icon">📊</span>
43
+ <span slot="content">Dashboard</span>
44
+ </IgrNavDrawerItem>
45
+ ```
46
+
47
+ > **Tip:** Check the component documentation for available slot names. Common slots include `start`, `end`, `prefix`, `suffix`, `header`, `content`, `icon`, `title`, `subtitle`.
48
+
49
+ ## Render Props (Grids & Complex Components)
50
+
51
+ Some components like the Data Grid support **render props** for custom cell rendering:
52
+
53
+ ```tsx
54
+ import { IgrGrid, IgrColumn } from 'igniteui-react-grids';
55
+
56
+ function UserGrid({ users }: { users: User[] }) {
57
+ return (
58
+ <IgrGrid data={users} autoGenerate={false}>
59
+ <IgrColumn field="name" header="Name" />
60
+ <IgrColumn field="email" header="Email" />
61
+ <IgrColumn
62
+ field="status"
63
+ header="Status"
64
+ bodyTemplate={(ctx) => (
65
+ <IgrBadge>{ctx.cell.value}</IgrBadge>
66
+ )}
67
+ />
68
+ </IgrGrid>
69
+ );
70
+ }
71
+ ```
72
+
73
+ ## IgrTabs — Content Panels vs Navigation
74
+
75
+ `IgrTabs` supports two distinct usage patterns. Choosing the wrong one is a common mistake.
76
+
77
+ ### Pattern 1: Tabs with Content Panels (inline content)
78
+
79
+ Use `IgrTab` with inline content when the tabbed content is rendered inline — no routing involved. The tab label can be set via a `label` prop or via a `slot="label"` element:
80
+
81
+ ```tsx
82
+ import { IgrTabs, IgrTab } from 'igniteui-react';
83
+
84
+ // Simple text labels using the label prop
85
+ function SettingsPage() {
86
+ return (
87
+ <IgrTabs>
88
+ <IgrTab label="Profile" selected>
89
+ <p>Profile settings content here</p>
90
+ </IgrTab>
91
+ <IgrTab label="Security">
92
+ <p>Security settings content here</p>
93
+ </IgrTab>
94
+ <IgrTab label="Notifications">
95
+ <p>Notification preferences content here</p>
96
+ </IgrTab>
97
+ </IgrTabs>
98
+ );
99
+ }
100
+ ```
101
+
102
+ **Alternative: Using slot="label" for complex headers (e.g., with icons):**
103
+
104
+ ```tsx
105
+ import { IgrTabs, IgrTab, IgrIcon } from 'igniteui-react';
106
+
107
+ function SettingsPage() {
108
+ return (
109
+ <IgrTabs>
110
+ <IgrTab selected>
111
+ <span slot="label">
112
+ <IgrIcon name="home" collection="material" />
113
+ Profile
114
+ </span>
115
+ <p>Profile settings content here</p>
116
+ </IgrTab>
117
+ <IgrTab>
118
+ <span slot="label">
119
+ <IgrIcon name="security" collection="material" />
120
+ Security
121
+ </span>
122
+ <p>Security settings content here</p>
123
+ </IgrTab>
124
+ <IgrTab>
125
+ <span slot="label">
126
+ <IgrIcon name="notifications" collection="material" />
127
+ Notifications
128
+ </span>
129
+ <p>Notification preferences content here</p>
130
+ </IgrTab>
131
+ </IgrTabs>
132
+ );
133
+ }
134
+ ```
135
+
136
+ ### Pattern 2: Tabs as Navigation (with React Router — NO inline content)
137
+
138
+ > **⚠️ CRITICAL:** When using `IgrTabs` for navigation with React Router (or any router), **do NOT include inline content in `IgrTab`**. Only render tab labels (via `label` prop or `slot="label"`), and let the router's `<Outlet />` handle the content below the tabs.
139
+
140
+ ```tsx
141
+ import { IgrTabs, IgrTab } from 'igniteui-react';
142
+ import { useNavigate, useLocation, Outlet } from 'react-router-dom';
143
+
144
+ const tabs = [
145
+ { path: '/dashboard', label: 'Dashboard' },
146
+ { path: '/orders', label: 'Orders' },
147
+ { path: '/customers', label: 'Customers' },
148
+ ];
149
+
150
+ function MainLayout() {
151
+ const navigate = useNavigate();
152
+ const location = useLocation();
153
+
154
+ const handleTabChange = (e: CustomEvent) => {
155
+ const selectedIndex = (e.target as any).selectedIndex;
156
+ if (selectedIndex !== undefined && tabs[selectedIndex]) {
157
+ navigate(tabs[selectedIndex].path);
158
+ }
159
+ };
160
+
161
+ return (
162
+ <div>
163
+ {/* Tabs for navigation — label prop only, no inline content */}
164
+ <IgrTabs onChange={handleTabChange}>
165
+ {tabs.map((tab) => (
166
+ <IgrTab
167
+ key={tab.path}
168
+ label={tab.label}
169
+ selected={location.pathname === tab.path}
170
+ />
171
+ ))}
172
+ </IgrTabs>
173
+
174
+ {/* Router outlet renders the routed view */}
175
+ <main>
176
+ <Outlet />
177
+ </main>
178
+ </div>
179
+ );
180
+ }
181
+ ```
182
+
183
+ **Key rules for tabs-as-navigation:**
184
+ - ✅ Use only `IgrTab` with label prop or `slot="label"` — no inline content
185
+ - ✅ Sync the active tab to the current route using the `selected` prop
186
+ - ✅ Handle `onChange` to call `navigate()` for route changes
187
+ - ✅ Use `<Outlet />` (or the equivalent in your router) for content rendering
@@ -0,0 +1,229 @@
1
+ # Refs & Forms
2
+
3
+ ## Refs & Imperative API
4
+
5
+ Use `useRef` to access the underlying web component element and call imperative methods (e.g., showing/hiding a dialog, focusing an input).
6
+ Components from `igniteui-react`, `igniteui-react-grids` and `igniteui-react-dockmanager` are React Function Components forward the native element to `useRef` and expose alias with the same name for accessing the custom element API:
7
+
8
+ ```tsx
9
+ import { useRef } from 'react';
10
+ import { IgrDialog, IgrButton, IgrInput } from 'igniteui-react';
11
+
12
+ function MyPage() {
13
+ const dialogRef = useRef<IgrDialog>(null);
14
+ const inputRef = useRef<IgrInput>(null);
15
+
16
+ const openDialog = () => {
17
+ // Access the underlying web component and call its methods
18
+ dialogRef.current?.show();
19
+ };
20
+
21
+ const focusInput = () => {
22
+ inputRef.current?.focus();
23
+ };
24
+
25
+ return (
26
+ <>
27
+ <IgrButton onClick={openDialog}>
28
+ <span>Open Dialog</span>
29
+ </IgrButton>
30
+
31
+ <IgrDialog ref={dialogRef} title="Confirmation">
32
+ <p>Are you sure?</p>
33
+ <IgrButton slot="footer" onClick={() => dialogRef.current?.hide()}>
34
+ <span>Close</span>
35
+ </IgrButton>
36
+ </IgrDialog>
37
+
38
+ <IgrButton onClick={focusInput}>
39
+ <span>Focus Input</span>
40
+ </IgrButton>
41
+ <IgrInput ref={inputRef} label="Name" />
42
+ </>
43
+ );
44
+ }
45
+ ```
46
+
47
+ > **Tip:** The ref gives you direct access to the web component's DOM element. You can call any method documented in the web component API.
48
+
49
+
50
+ ## Uncontrolled Components
51
+
52
+ `igniteui-react` Inputs integrate with the native form handling through Element internals, allowing to take advantage of the native state management adn validation to create intuitive, straight-forward forms:
53
+
54
+ ```tsx
55
+ import { useRef } from 'react';
56
+ import { IgrInput, IgrButton } from 'igniteui-react';
57
+
58
+ function SimpleForm() {
59
+ const nameRef = useRef<IgrInput>(null);
60
+
61
+ const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
62
+ // e.preventDefault(); // optionally prevent default submit form custom handling
63
+ const formData = new FormData(e.target);
64
+ };
65
+
66
+ return (
67
+ <form onSubmit={handleSubmit}>
68
+ <IgrInput name="name" label="Name" required={true} />
69
+ <IgrInput name="description" label="description" minLength={0}>
70
+ <IgrButton type="submit">
71
+ <span>Submit</span>
72
+ </IgrButton>
73
+ </form>
74
+ );
75
+ }
76
+ ```
77
+
78
+ ## Controlled Components with `useState`
79
+
80
+ Wire up Ignite UI form components with React state for controlled behavior:
81
+
82
+ ```tsx
83
+ import { useState } from 'react';
84
+ import { IgrInput, IgrCheckbox, IgrSelect, IgrSelectItem } from 'igniteui-react';
85
+
86
+ function ProfileForm() {
87
+ const [name, setName] = useState('');
88
+ const [newsletter, setNewsletter] = useState(false);
89
+ const [role, setRole] = useState('user');
90
+
91
+ return (
92
+ <form>
93
+ <IgrInput
94
+ label="Name"
95
+ value={name}
96
+ onInput={(e: CustomEvent<string>) => setName(e.detail) }
97
+ />
98
+
99
+ <IgrCheckbox
100
+ checked={newsletter}
101
+ onChange={(e: CustomEvent<IgcCheckboxChangeEventArgs>) =>
102
+ setNewsletter(e.detail.checked)
103
+ }
104
+ >
105
+ Subscribe to newsletter
106
+ </IgrCheckbox>
107
+
108
+ <IgrSelect
109
+ label="Role"
110
+ value={role}
111
+ onChange={(e: CustomEvent<IgcSelectItemComponent>) =>
112
+ setRole(e.detail.value)
113
+ }
114
+ >
115
+ <IgrSelectItem value="user">User</IgrSelectItem>
116
+ <IgrSelectItem value="admin">Admin</IgrSelectItem>
117
+ <IgrSelectItem value="editor">Editor</IgrSelectItem>
118
+ </IgrSelect>
119
+ </form>
120
+ );
121
+ }
122
+ ```
123
+
124
+ ## React Hook Form Integration
125
+
126
+ Ignite UI components are form-associated web components. You can integrate them with React Hook Form using `Controller`:
127
+
128
+ ```tsx
129
+ import { useForm, Controller } from 'react-hook-form';
130
+ import { IgrInput, IgrCheckbox, IgrButton } from 'igniteui-react';
131
+
132
+ interface FormData {
133
+ email: string;
134
+ acceptTerms: boolean;
135
+ }
136
+
137
+ function SignUpForm() {
138
+ const { control, handleSubmit, formState: { errors } } = useForm<FormData>();
139
+
140
+ const onSubmit = (data: FormData) => {
141
+ console.log(data);
142
+ };
143
+
144
+ return (
145
+ <form onSubmit={handleSubmit(onSubmit)}>
146
+ <Controller
147
+ name="email"
148
+ control={control}
149
+ rules={{ required: 'Email is required' }}
150
+ render={({ field }) => (
151
+ <IgrInput
152
+ label="Email"
153
+ type="email"
154
+ value={field.value || ''}
155
+ onInput={(e: CustomEvent<string>) =>
156
+ field.onChange(e.detail)
157
+ }
158
+ onBlur={() => field.onBlur()}
159
+ invalid={!!errors.email}
160
+ />
161
+ )}
162
+ />
163
+ {errors.email && <span>{errors.email.message}</span>}
164
+
165
+ <Controller
166
+ name="acceptTerms"
167
+ control={control}
168
+ rules={{ required: 'You must accept the terms' }}
169
+ render={({ field }) => (
170
+ <IgrCheckbox
171
+ checked={field.value || false}
172
+ onChange={(e: CustomEvent<IgcCheckboxChangeEventArgs>) =>
173
+ field.onChange(e.detail.checked)
174
+ }
175
+ >
176
+ I accept the terms and conditions
177
+ </IgrCheckbox>
178
+ )}
179
+ />
180
+
181
+ <IgrButton type="submit">
182
+ <span>Sign Up</span>
183
+ </IgrButton>
184
+ </form>
185
+ );
186
+ }
187
+ ```
188
+
189
+ ## TypeScript
190
+
191
+ ### Importing Component Types
192
+
193
+ Each component exports its props interface. Import and use them for type-safe code:
194
+
195
+ ```tsx
196
+ import { IgrButton, IgrInput } from 'igniteui-react';
197
+ import type { ComponentProps } from 'react';
198
+
199
+ // Get the props type for a component
200
+ type ButtonProps = ComponentProps<typeof IgrButton>;
201
+ type InputProps = ComponentProps<typeof IgrInput>;
202
+
203
+ // Use in your own components
204
+ interface FormFieldProps {
205
+ label: string;
206
+ inputProps?: Partial<InputProps>;
207
+ }
208
+
209
+ function FormField({ label, inputProps }: FormFieldProps) {
210
+ return (
211
+ <div>
212
+ <IgrInput label={label} {...inputProps} />
213
+ </div>
214
+ );
215
+ }
216
+ ```
217
+
218
+ ### Auto-complete
219
+
220
+ IDEs with TypeScript support will provide auto-complete for all `Igr*` component props. Make sure your `tsconfig.json` includes:
221
+
222
+ ```json
223
+ {
224
+ "compilerOptions": {
225
+ "jsx": "react-jsx",
226
+ "moduleResolution": "bundler"
227
+ }
228
+ }
229
+ ```