@indico-data/design-system 2.4.2 → 2.6.0

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 (44) hide show
  1. package/.storybook/preview.ts +4 -14
  2. package/lib/index.css +208 -0
  3. package/lib/index.d.ts +31 -3
  4. package/lib/index.esm.css +208 -0
  5. package/lib/index.esm.js +23 -1
  6. package/lib/index.esm.js.map +1 -1
  7. package/lib/index.js +24 -0
  8. package/lib/index.js.map +1 -1
  9. package/lib/src/components/forms/input/Input.d.ts +18 -0
  10. package/lib/src/components/forms/input/Input.stories.d.ts +12 -0
  11. package/lib/src/components/forms/input/__tests__/Input.test.d.ts +1 -0
  12. package/lib/src/components/forms/input/index.d.ts +1 -0
  13. package/lib/src/components/forms/radio/Radio.d.ts +11 -0
  14. package/lib/src/components/forms/radio/Radio.stories.d.ts +6 -0
  15. package/lib/src/components/forms/radio/__tests__/Radio.test.d.ts +1 -0
  16. package/lib/src/components/forms/radio/index.d.ts +1 -0
  17. package/lib/src/components/forms/subcomponents/ErrorList.d.ts +6 -0
  18. package/lib/src/components/forms/subcomponents/Label.d.ts +8 -0
  19. package/lib/src/components/forms/subcomponents/__tests__/ErrorList.test.d.ts +1 -0
  20. package/lib/src/components/forms/subcomponents/__tests__/Label.test.d.ts +1 -0
  21. package/lib/src/components/index.d.ts +2 -0
  22. package/lib/src/index.d.ts +2 -0
  23. package/package.json +1 -1
  24. package/src/components/forms/input/Input.mdx +19 -0
  25. package/src/components/forms/input/Input.stories.tsx +301 -0
  26. package/src/components/forms/input/Input.tsx +86 -0
  27. package/src/components/forms/input/__tests__/Input.test.tsx +213 -0
  28. package/src/components/forms/input/index.ts +1 -0
  29. package/src/components/forms/input/styles/Input.scss +112 -0
  30. package/src/components/forms/radio/Radio.mdx +83 -0
  31. package/src/components/forms/radio/Radio.stories.tsx +121 -0
  32. package/src/components/forms/radio/Radio.tsx +47 -0
  33. package/src/components/forms/radio/__tests__/Radio.test.tsx +35 -0
  34. package/src/components/forms/radio/index.ts +1 -0
  35. package/src/components/forms/radio/styles/Radio.scss +98 -0
  36. package/src/components/forms/subcomponents/ErrorList.tsx +14 -0
  37. package/src/components/forms/subcomponents/Label.tsx +20 -0
  38. package/src/components/forms/subcomponents/__tests__/ErrorList.test.tsx +16 -0
  39. package/src/components/forms/subcomponents/__tests__/Label.test.tsx +33 -0
  40. package/src/components/index.ts +2 -0
  41. package/src/index.ts +2 -0
  42. package/src/styles/_typography.scss +29 -11
  43. package/src/styles/index.scss +2 -0
  44. package/src/styles/storybook.scss +15 -0
@@ -0,0 +1,98 @@
1
+ // Common Variables
2
+ :root,
3
+ :root [data-theme='light'],
4
+ :root [data-theme='dark'] {
5
+ --pf-radio-background-color: var(--pf-white-color);
6
+ --pf-radio-check-color: var(--pf-primary-color);
7
+ --pf-radio-border-color: var(--pf-gray-color);
8
+ --pf-radio-disabled-color: var(--pf-gray-color-400);
9
+ }
10
+
11
+ // Dark Theme Specific Variables
12
+ :root [data-theme='dark'] {
13
+ --pf-radio-background-color: transparent;
14
+ --pf-radio-check-color: var(--pf-white-color);
15
+ --pf-radio-border-color: var(--pf-white-color);
16
+ --pf-radio-disabled-color: var(--pf-gray-color-300);
17
+ }
18
+
19
+ .form-control {
20
+ .radio-wrapper {
21
+ display: flex;
22
+ margin-bottom: var(--pf-margin-2);
23
+ align-items: center;
24
+ }
25
+ .radio-input {
26
+ margin: 0;
27
+ margin-right: var(--pf-margin-2);
28
+ cursor: pointer;
29
+ }
30
+ .radio-input-label {
31
+ cursor: pointer;
32
+ }
33
+ [type='radio']:checked,
34
+ [type='radio']:not(:checked) {
35
+ position: absolute;
36
+ left: -9999px;
37
+ }
38
+ [type='radio']:checked + label,
39
+ [type='radio']:not(:checked) + label {
40
+ position: relative;
41
+ padding-left: var(--pf-padding-7);
42
+ cursor: pointer;
43
+ line-height: 20px;
44
+ display: inline-block;
45
+ }
46
+ [type='radio']:checked + label:before,
47
+ [type='radio']:not(:checked) + label:before {
48
+ content: '';
49
+ position: absolute;
50
+ left: 0;
51
+ top: 0;
52
+ width: 18px;
53
+ height: 18px;
54
+ border: 1px solid var(--pf-radio-border-color);
55
+ border-radius: 100%;
56
+ background: var(--pf-radio-background-color);
57
+ }
58
+ [type='radio']:checked + label:after,
59
+ [type='radio']:not(:checked) + label:after {
60
+ content: '';
61
+ width: 12px;
62
+ height: 12px;
63
+ background: var(--pf-radio-check-color);
64
+ position: absolute;
65
+ top: 4px;
66
+ left: 4px;
67
+ border-radius: 100%;
68
+ -webkit-transition: all 0.2s ease;
69
+ transition: all 0.2s ease;
70
+ }
71
+ [type='radio']:not(:checked) + label:after {
72
+ opacity: 0;
73
+ -webkit-transform: scale(0);
74
+ transform: scale(0);
75
+ }
76
+ [type='radio']:checked + label:after {
77
+ opacity: 1;
78
+ -webkit-transform: scale(1);
79
+ transform: scale(1);
80
+ }
81
+ [type='radio']:disabled,
82
+ [type='radio']:disabled + label {
83
+ cursor: not-allowed;
84
+ }
85
+
86
+ [type='radio']:disabled + label {
87
+ color: var(--pf-radio-disabled-color);
88
+ opacity: 0.5;
89
+ }
90
+
91
+ [type='radio']:disabled + label:before {
92
+ border-color: var(--pf-radio-disabled-color);
93
+ }
94
+
95
+ [type='radio']:disabled + label:after {
96
+ background: var(--pf-radio-disabled-color);
97
+ }
98
+ }
@@ -0,0 +1,14 @@
1
+ interface ErrorListProps {
2
+ name: string;
3
+ errorList: string[];
4
+ }
5
+
6
+ export const ErrorList = ({ errorList, name }: ErrorListProps) => {
7
+ return (
8
+ <ul className="error-list" id={`${name}-helper`}>
9
+ {(errorList ?? []).map((error, index) => (
10
+ <li key={index}>{error}</li>
11
+ ))}
12
+ </ul>
13
+ );
14
+ };
@@ -0,0 +1,20 @@
1
+ interface LabelProps {
2
+ label: string;
3
+ name: string;
4
+ isRequired?: boolean;
5
+ hasHiddenLabel?: boolean;
6
+ }
7
+
8
+ export const Label = ({ label, name, isRequired, hasHiddenLabel }: LabelProps) => {
9
+ return (
10
+ <div
11
+ data-testid={`${name}-testId`}
12
+ className={`form-label ${hasHiddenLabel ? 'is-visually-hidden' : ''}`}
13
+ >
14
+ <label htmlFor={`${name}`}>
15
+ {label}
16
+ {isRequired ? <span className="text-error"> *</span> : ''}
17
+ </label>
18
+ </div>
19
+ );
20
+ };
@@ -0,0 +1,16 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import { ErrorList } from '@/components/forms/subcomponents/ErrorList';
3
+
4
+ describe('ErrorList', () => {
5
+ it('renders the error list', () => {
6
+ render(<ErrorList name="name" errorList={['error1', 'error2']} />);
7
+ expect(screen.getByText('error1')).toBeInTheDocument();
8
+ expect(screen.getByText('error2')).toBeInTheDocument();
9
+ });
10
+
11
+ it('does not render the error list when it is empty', () => {
12
+ render(<ErrorList name="name" errorList={[]} />);
13
+ expect(screen.queryByText('error1')).not.toBeInTheDocument();
14
+ expect(screen.queryByText('error2')).not.toBeInTheDocument();
15
+ });
16
+ });
@@ -0,0 +1,33 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import { Label } from '@/components/forms/subcomponents/Label';
3
+
4
+ describe('Label', () => {
5
+ it('renders the `required` astherisc when the label is required', () => {
6
+ render(<Label label={'name'} name={'name'} isRequired={true} hasHiddenLabel={false} />);
7
+ expect(screen.getByText('*')).toBeInTheDocument();
8
+ expect(screen.getByText('*')).toBeVisible();
9
+ });
10
+ it('does not render the `required` astherisc when the label is not required', () => {
11
+ render(<Label label={'name'} name={'name'} isRequired={false} hasHiddenLabel={false} />);
12
+ expect(screen.queryByText('*')).not.toBeInTheDocument();
13
+ expect(screen.queryByText('*')).toBeNull();
14
+ });
15
+ it('renders the label for screen readers while hidden visually', () => {
16
+ render(<Label label={'name'} name={'name'} isRequired={false} hasHiddenLabel={true} />);
17
+ expect(screen.getByText('name')).toBeInTheDocument();
18
+ expect(screen.getByText('name')).toBeVisible();
19
+ });
20
+ it('renders the label text', () => {
21
+ render(<Label label={'name'} name={'name'} isRequired={false} hasHiddenLabel={false} />);
22
+ const label = screen.getByTestId('name-testId');
23
+ expect(label).toBeInTheDocument();
24
+ expect(label).toBeVisible();
25
+ expect(label).not.toHaveClass('is-visually-hidden');
26
+ });
27
+
28
+ it('renders the label text when the label is hidden', () => {
29
+ render(<Label label={'name'} name={'name'} isRequired={false} hasHiddenLabel={true} />);
30
+ const label = screen.getByTestId('name-testId');
31
+ expect(label).toHaveClass('is-visually-hidden');
32
+ });
33
+ });
@@ -2,3 +2,5 @@ export { Container, Col, Row } from './grid';
2
2
  export { Button } from './button';
3
3
  export { Icon } from './icons';
4
4
  export { Table } from './table';
5
+ export { Input } from './forms/input';
6
+ export { Radio } from './forms/radio';
package/src/index.ts CHANGED
@@ -61,3 +61,5 @@ export { Container, Row, Col } from './components/grid';
61
61
  export { Button } from './components/button';
62
62
  export { Icon } from './components/icons';
63
63
  export { Table } from './components/table';
64
+ export { Input } from './components/forms/input';
65
+ export { Radio as RadioInput } from './components/forms/radio';
@@ -5,14 +5,17 @@ html {
5
5
  font-family: var(--pf-font-family-base);
6
6
  }
7
7
  // Font Sizing and Family
8
- @each $tag, $size in (
9
- h1: --pf-font-size-h1,
10
- h2: --pf-font-size-h2,
11
- h3: --pf-font-size-h3,
12
- h4: --pf-font-size-h4,
13
- h5: --pf-font-size-h5,
14
- p: --pf-font-size-body) {
15
-
8
+ @each $tag,
9
+ $size
10
+ in (
11
+ h1: --pf-font-size-h1,
12
+ h2: --pf-font-size-h2,
13
+ h3: --pf-font-size-h3,
14
+ h4: --pf-font-size-h4,
15
+ h5: --pf-font-size-h5,
16
+ p: --pf-font-size-body
17
+ )
18
+ {
16
19
  #{$tag},
17
20
  .text-#{$tag} {
18
21
  font-size: var(#{$size});
@@ -21,9 +24,8 @@ html {
21
24
  padding: 0;
22
25
 
23
26
  // If the tag is not 'p', make it bold
24
- @if $tag !='p' {
27
+ @if $tag != 'p' {
25
28
  font-weight: var(--pf-font-weight-bold);
26
-
27
29
  }
28
30
  }
29
31
  }
@@ -46,7 +48,6 @@ html {
46
48
  font-size: var(--pf-font-size-overine);
47
49
  }
48
50
 
49
-
50
51
  // Transform
51
52
  .text-capitalize {
52
53
  text-transform: capitalize;
@@ -114,3 +115,20 @@ html {
114
115
  .text-break--word {
115
116
  overflow-wrap: break-word;
116
117
  }
118
+
119
+ // Text Colors
120
+ .text-error {
121
+ color: var(--pf-error-color);
122
+ }
123
+
124
+ .text-warning {
125
+ color: var(--pf-warning-color);
126
+ }
127
+
128
+ .text-success {
129
+ color: var(--pf-success-color);
130
+ }
131
+
132
+ .text-info {
133
+ color: var(--pf-info-color);
134
+ }
@@ -6,6 +6,8 @@
6
6
  @import '../components/icons/styles/Icon.scss';
7
7
  @import '../components/grid/styles/Grid.scss';
8
8
  @import '../components/table/styles/Table.scss';
9
+ @import '../components/forms/input/styles/Input.scss';
10
+ @import '../components/forms/radio/styles/Radio.scss';
9
11
 
10
12
  @import 'typography';
11
13
  @import 'colors';
@@ -0,0 +1,15 @@
1
+ :root [data-theme='light'],
2
+ :root {
3
+ --storybook-bg-color: var(--pf-white-color);
4
+ --storybook-font-color: var(--pf-gray-color);
5
+ }
6
+
7
+ :root [data-theme='dark'] {
8
+ --storybook-bg-color: var(--pf-primary-color-300);
9
+ --storybook-font-color: var(--pf-white-color);
10
+ }
11
+
12
+ .sb__story {
13
+ background-color: var(--storybook-bg-color);
14
+ color: var(--storybook-font-color);
15
+ }