Skip to content

Commit 0e0c464

Browse files
docs(input): Add input docs
1 parent 5a63ea7 commit 0e0c464

File tree

5 files changed

+310
-4
lines changed

5 files changed

+310
-4
lines changed

projects/docs/src/app/pages/docs/components/components.routes.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ export const routes: Routes = [
6464
path: 'label',
6565
loadComponent: () => import('./label/label').then(m => m.Label)
6666
},
67+
{
68+
path: 'input',
69+
loadComponent: () => import('./input/input').then(m => m.Input)
70+
},
6771
{
6872
path: 'table',
6973
loadComponent: () => import('./table/table').then(m => m.Table)
Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
import { Component } from '@angular/core';
2+
import { UiDescription, UiFormField, UiInput, UiButton, UiLabel } from 'ui';
3+
import { IVariant, IComponentMeta } from '@components/component-preview/component-preview';
4+
import { FormsModule } from '@angular/forms';
5+
6+
@Component({
7+
selector: 'input-default-example',
8+
template: `
9+
<input uiInput type="email" placeholder="Email" [(ngModel)]="email" required />
10+
`,
11+
imports: [UiInput, FormsModule],
12+
standalone: true,
13+
host: {
14+
'class': 'w-2/3 space-y-6 mx-auto'
15+
},
16+
})
17+
export class InputDefaultExample {
18+
email = '';
19+
}
20+
21+
@Component({
22+
selector: 'input-file-example',
23+
template: `
24+
<div class="grid w-full max-w-sm items-center gap-3" uiFormField>
25+
<label uiLabel for="picture">Picture</label>
26+
<input uiInput id="picture" type="file" />
27+
</div>
28+
`,
29+
imports: [UiInput, UiLabel, UiFormField],
30+
standalone: true,
31+
host: {
32+
'class': 'w-2/3 space-y-6 mx-auto'
33+
},
34+
})
35+
export class InputFileExample {}
36+
37+
@Component({
38+
selector: 'input-disabled-example',
39+
template: `
40+
<input uiInput disabled type="email" placeholder="Email" [(ngModel)]="disabledEmail" />
41+
`,
42+
imports: [UiInput, FormsModule],
43+
standalone: true,
44+
host: {
45+
'class': 'w-2/3 space-y-6 mx-auto'
46+
},
47+
})
48+
export class InputDisabledExample {
49+
disabledEmail = 'disabled@example.com';
50+
}
51+
52+
@Component({
53+
selector: 'input-with-label-example',
54+
template: `
55+
<div class="grid w-full max-w-sm items-center gap-3" uiFormField>
56+
<label uiLabel for="email">Email</label>
57+
<input uiInput type="email" id="email" placeholder="Email" [(ngModel)]="email" />
58+
</div>
59+
`,
60+
imports: [UiInput, UiLabel, UiFormField, FormsModule],
61+
standalone: true,
62+
host: {
63+
'class': 'w-2/3 space-y-6 mx-auto'
64+
}
65+
})
66+
export class InputWithLabelExample {
67+
email = '';
68+
}
69+
70+
@Component({
71+
selector: 'input-with-button-example',
72+
template: `
73+
<div class="flex w-full max-w-sm items-center gap-2">
74+
<input uiInput type="email" placeholder="Email" [(ngModel)]="subscribeEmail" />
75+
<button uiButton type="submit" variant="outline">
76+
Subscribe
77+
</button>
78+
</div>
79+
`,
80+
imports: [UiInput, UiButton, FormsModule],
81+
standalone: true,
82+
host: {
83+
'class': 'w-2/3 space-y-6 mx-auto'
84+
}
85+
})
86+
export class InputWithButtonExample {
87+
subscribeEmail = '';
88+
}
89+
90+
@Component({
91+
selector: 'input-form-example',
92+
template: `
93+
<form (ngSubmit)="onSubmit()">
94+
<div class="grid items-center gap-1.5" uiFormField>
95+
<label uiLabel>Username</label>
96+
<input uiInput placeholder="slateui" [(ngModel)]="username" name="username" />
97+
<p uiDescription>This is your public display name.</p>
98+
</div>
99+
<button uiButton type="submit">Submit</button>
100+
</form>
101+
`,
102+
imports: [UiInput, UiLabel, UiButton, FormsModule, UiFormField, UiDescription],
103+
standalone: true,
104+
host: {
105+
'class': 'w-2/3 space-y-6 mx-auto'
106+
},
107+
})
108+
export class InputFormExample {
109+
username = '';
110+
111+
onSubmit() {
112+
console.log('Form submitted:', { username: this.username });
113+
}
114+
}
115+
116+
export const inputMeta: IComponentMeta = {
117+
title: 'Input',
118+
description: 'A form input component with various types and states.',
119+
installation: {
120+
package: 'input',
121+
import: `import { UiInput } from '@workspace/ui/directives/input';`,
122+
usage: `<input uiInput type="text" placeholder="Enter text" />`
123+
},
124+
api: {
125+
props: [
126+
{ name: 'uiInput', type: 'Directive', description: 'Input directive for styling and functionality.' },
127+
{ name: 'type', type: 'string', description: 'HTML input type (text, email, password, etc.).' },
128+
{ name: 'placeholder', type: 'string', description: 'Placeholder text for the input.' },
129+
{ name: 'disabled', type: 'boolean', description: 'Whether the input is disabled.' },
130+
{ name: 'class', type: 'string', description: 'Additional CSS classes.' }
131+
]
132+
}
133+
};
134+
135+
export const inputVariants: IVariant[] = [
136+
{
137+
title: 'Default',
138+
description: 'Basic input field.',
139+
code: `import { UiInput } from '@workspace/ui/directives/input';
140+
import { FormsModule } from '@angular/forms';
141+
142+
@Component({
143+
selector: 'input-default-example',
144+
template: \`
145+
<input uiInput type="email" placeholder="Email" [(ngModel)]="email" />
146+
\`,
147+
imports: [UiInput, FormsModule],
148+
standalone: true
149+
})
150+
export class InputDefaultExample {
151+
email = '';
152+
}`,
153+
component: InputDefaultExample
154+
},
155+
{
156+
title: 'File',
157+
description: 'File input for uploading documents and images.',
158+
code: `import { UiInput } from '@workspace/ui/directives/input';
159+
import { UiLabel } from '@workspace/ui/directives/label';
160+
import { UiFormField } from '@workspace/ui/directives/form-field';
161+
162+
@Component({
163+
selector: 'input-file-example',
164+
template: \`
165+
<div class="grid w-full max-w-sm items-center gap-3" uiFormField>
166+
<label uiLabel for="picture">Picture</label>
167+
<input uiInput id="picture" type="file" />
168+
</div>
169+
\`,
170+
imports: [UiInput, UiLabel, UiFormField],
171+
standalone: true
172+
})
173+
export class InputFileExample {}`,
174+
component: InputFileExample
175+
},
176+
{
177+
title: 'Disabled',
178+
description: 'Disabled input field that cannot be interacted with.',
179+
code: `import { UiInput } from '@workspace/ui/directives/input';
180+
import { FormsModule } from '@angular/forms';
181+
182+
@Component({
183+
selector: 'input-disabled-example',
184+
template: \`
185+
<input uiInput disabled type="email" placeholder="Email" [(ngModel)]="disabledEmail" />
186+
\`,
187+
imports: [UiInput, FormsModule],
188+
standalone: true
189+
})
190+
export class InputDisabledExample {
191+
disabledEmail = 'disabled@example.com';
192+
}`,
193+
component: InputDisabledExample
194+
},
195+
{
196+
title: 'With Label',
197+
description: 'Input field with associated label for accessibility.',
198+
code: `import { UiInput } from '@workspace/ui/directives/input';
199+
import { UiLabel } from '@workspace/ui/directives/label';
200+
import { UiFormField } from '@workspace/ui/directives/form-field';
201+
import { FormsModule } from '@angular/forms';
202+
203+
@Component({
204+
selector: 'input-with-label-example',
205+
template: \`
206+
<div class="grid w-full max-w-sm items-center gap-3" uiFormField>
207+
<label uiLabel for="email">Email</label>
208+
<input uiInput type="email" id="email" placeholder="Email" [(ngModel)]="email" />
209+
</div>
210+
\`,
211+
imports: [UiInput, UiLabel, UiFormField, FormsModule],
212+
standalone: true
213+
})
214+
export class InputWithLabelExample {
215+
email = '';
216+
}`,
217+
component: InputWithLabelExample
218+
},
219+
{
220+
title: 'With Button',
221+
description: 'Input field with a submit button.',
222+
code: `import { UiInput } from '@workspace/ui/directives/input';
223+
import { UiButton } from '@workspace/ui/directives/button';
224+
import { FormsModule } from '@angular/forms';
225+
226+
@Component({
227+
selector: 'input-with-button-example',
228+
template: \`
229+
<div class="flex w-full max-w-sm items-center gap-2">
230+
<input uiInput type="email" placeholder="Email" [(ngModel)]="subscribeEmail" />
231+
<button uiButton type="submit" variant="outline">
232+
Subscribe
233+
</button>
234+
</div>
235+
\`,
236+
imports: [UiInput, UiButton, FormsModule],
237+
standalone: true
238+
})
239+
export class InputWithButtonExample {
240+
subscribeEmail = '';
241+
}`,
242+
component: InputWithButtonExample
243+
},
244+
{
245+
title: 'Form',
246+
description: 'Simple form with input field using ngModel and form field directives.',
247+
code: `import { UiInput } from '@workspace/ui/directives/input';
248+
import { UiButton } from '@workspace/ui/directives/button';
249+
import { UiFormField, UiDescription, UiLabel } from '@workspace/ui/directives/form-field';
250+
import { FormsModule } from '@angular/forms';
251+
252+
@Component({
253+
selector: 'input-form-example',
254+
template: \`
255+
<form (ngSubmit)="onSubmit()">
256+
<div class="grid items-center gap-1.5" uiFormField>
257+
<label uiLabel for="username">Username</label>
258+
<input uiInput placeholder="slateui" [(ngModel)]="username" name="username" />
259+
<p uiDescription>This is your public display name.</p>
260+
</div>
261+
<button uiButton type="submit">Submit</button>
262+
</form>
263+
\`,
264+
imports: [UiInput, UiLabel, UiButton, UiFormField, UiDescription, FormsModule],
265+
standalone: true
266+
})
267+
export class InputFormExample {
268+
username = '';
269+
270+
onSubmit() {
271+
console.log('Form submitted:', { username: this.username });
272+
}
273+
}`,
274+
component: InputFormExample
275+
}
276+
];

projects/docs/src/app/shared/components/sidebar/sidebar.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export class Sidebar {
4646
links: [
4747
{ name: 'Accordion', path: 'accordion' },
4848
{ name: 'Alert', path: 'alert' },
49+
{ name: 'Alert Dialog', path: 'alert-dialog' },
4950
{ name: 'Avatar', path: 'avatar' },
5051
{ name: 'Badge', path: 'badge' },
5152
{ name: 'Button', path: 'button' },
@@ -54,8 +55,8 @@ export class Sidebar {
5455
// { name: 'Checkbox', path: 'checkbox' },
5556
{ name: 'Dialog', path: 'dialog' },
5657
{ name: 'Dropdown Menu', path: 'dropdown-menu' },
57-
// { name: 'Label', path: 'label' },
58-
// { name: 'Input', path: 'input' },
58+
// { name: 'Label', path: 'label' },
59+
{ name: 'Input', path: 'input' },
5960
{ name: 'Popover', path: 'popover' },
6061
{ name: 'Progress', path: 'progress' },
6162
// { name: 'Select', path: 'select' },
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { computed, Directive, input } from "@angular/core";
2+
import { tv } from "tailwind-variants";
3+
import { NgpInput } from "ng-primitives/input";
4+
5+
const inputVariants = tv({
6+
base: ["file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium data-[disabled]:pointer-events-none data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 md:text-sm",
7+
"data-[focus]:border-ring data-[focus]:ring-ring/50 data-[focus]:ring-[3px]",
8+
"aria-invalid:ring-destructive/20 [&.ng-invalid.ng-touched]:ring-destructive/20 [&.ng-invalid.ng-touched]:border-destructive dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"].join(' ')
9+
});
10+
11+
@Directive({
12+
selector: 'input[uiInput]',
13+
exportAs: 'uiInput',
14+
host: {
15+
'[class]': 'computedClass()'
16+
},
17+
hostDirectives: [NgpInput],
18+
})
19+
export class UiInput {
20+
inputClass = input<string>('', { alias: 'class' });
21+
computedClass = computed(() => inputVariants({ class: this.inputClass() }));
22+
}
23+

projects/ui/src/public-api.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ export * from './directives/card';
66
export * from './directives/accordion';
77
export * from './directives/dialog';
88
export * from './directives/alert-dialog';
9+
export * from './directives/input';
910
export * from './directives/tooltip';
1011
export * from './directives/popover';
1112
export * from './directives/separator';
12-
export * from './directives/label';
13+
// export * from './directives/label';
1314
export * from './directives/progress';
1415
export * from './directives/tabs';
1516
export * from './directives/dropdown-menu';
1617
export * from './directives/table';
17-
export * from './directives/breadcrumb';
18+
export * from './directives/breadcrumb';
19+
export * from './directives/form-field';

0 commit comments

Comments
 (0)