create-template-html-css 2.0.3 → 2.1.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 (74) hide show
  1. package/CHANGELOG.md +305 -0
  2. package/HTML-VS-REACT.md +289 -0
  3. package/QUICKSTART-REACT.md +293 -0
  4. package/REACT-SUPPORT-SUMMARY.md +235 -0
  5. package/README.md +193 -12
  6. package/bin/cli.js +98 -759
  7. package/bin/commands/create.js +272 -0
  8. package/bin/commands/gallery.js +42 -0
  9. package/bin/commands/insert.js +123 -0
  10. package/bin/commands/list.js +73 -0
  11. package/package.json +10 -3
  12. package/src/component-choices.js +7 -0
  13. package/src/components-registry.js +112 -0
  14. package/src/format-utils.js +49 -0
  15. package/src/generator.js +83 -594
  16. package/src/generators/color-schemes.js +78 -0
  17. package/src/generators/color-utils.js +108 -0
  18. package/src/generators/component-filters.js +151 -0
  19. package/src/generators/html-generators.js +180 -0
  20. package/src/generators/validation.js +43 -0
  21. package/src/index.js +2 -1
  22. package/src/inserter.js +55 -233
  23. package/src/inserters/backup-utils.js +20 -0
  24. package/src/inserters/component-loader.js +68 -0
  25. package/src/inserters/html-utils.js +31 -0
  26. package/src/inserters/indentation-utils.js +90 -0
  27. package/src/inserters/validation-utils.js +49 -0
  28. package/src/react-component-choices.js +45 -0
  29. package/src/react-file-operations.js +172 -0
  30. package/src/react-generator.js +208 -0
  31. package/src/react-templates.js +350 -0
  32. package/src/utils/file-utils.js +97 -0
  33. package/src/utils/path-utils.js +32 -0
  34. package/src/utils/string-utils.js +51 -0
  35. package/src/utils/template-loader.js +91 -0
  36. package/templates/_shared/PATTERNS.md +246 -0
  37. package/templates/_shared/README.md +74 -0
  38. package/templates/_shared/base.css +18 -0
  39. package/templates/blackjack/index.html +1 -1
  40. package/templates/blackjack/script.js +9 -9
  41. package/templates/breakout/index.html +1 -1
  42. package/templates/breakout/script.js +6 -6
  43. package/templates/connect-four/index.html +1 -1
  44. package/templates/connect-four/script.js +5 -5
  45. package/templates/dice-game/index.html +1 -1
  46. package/templates/dice-game/script.js +20 -20
  47. package/templates/flappy-bird/index.html +1 -1
  48. package/templates/flappy-bird/script.js +10 -10
  49. package/templates/pong/index.html +1 -1
  50. package/templates/pong/script.js +8 -8
  51. package/templates/skeleton/index.html +4 -4
  52. package/templates/slot-machine/index.html +1 -1
  53. package/templates/slot-machine/script.js +6 -6
  54. package/templates/tetris/index.html +1 -1
  55. package/templates/tetris/script.js +5 -5
  56. package/templates-react/README.md +126 -0
  57. package/templates-react/button/Button.css +88 -0
  58. package/templates-react/button/Button.example.jsx +40 -0
  59. package/templates-react/button/Button.jsx +29 -0
  60. package/templates-react/card/Card.css +86 -0
  61. package/templates-react/card/Card.example.jsx +49 -0
  62. package/templates-react/card/Card.jsx +35 -0
  63. package/templates-react/counter/Counter.css +99 -0
  64. package/templates-react/counter/Counter.example.jsx +45 -0
  65. package/templates-react/counter/Counter.jsx +70 -0
  66. package/templates-react/form/Form.css +128 -0
  67. package/templates-react/form/Form.example.jsx +65 -0
  68. package/templates-react/form/Form.jsx +125 -0
  69. package/templates-react/modal/Modal.css +152 -0
  70. package/templates-react/modal/Modal.example.jsx +90 -0
  71. package/templates-react/modal/Modal.jsx +46 -0
  72. package/templates-react/todo-list/TodoList.css +236 -0
  73. package/templates-react/todo-list/TodoList.example.jsx +15 -0
  74. package/templates-react/todo-list/TodoList.jsx +84 -0
@@ -0,0 +1,99 @@
1
+ /* Counter Styles */
2
+ .counter-container {
3
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
4
+ background: white;
5
+ padding: 40px;
6
+ border-radius: 20px;
7
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
8
+ max-width: 400px;
9
+ margin: 0 auto;
10
+ text-align: center;
11
+ }
12
+
13
+ .counter-title {
14
+ font-size: 32px;
15
+ font-weight: 700;
16
+ margin: 0 0 30px 0;
17
+ background: linear-gradient(135deg, {{primaryColor}} 0%, {{secondaryColor}} 100%);
18
+ -webkit-background-clip: text;
19
+ -webkit-text-fill-color: transparent;
20
+ background-clip: text;
21
+ }
22
+
23
+ .counter-display {
24
+ font-size: 96px;
25
+ font-weight: 800;
26
+ background: linear-gradient(135deg, {{primaryColor}} 0%, {{secondaryColor}} 100%);
27
+ -webkit-background-clip: text;
28
+ -webkit-text-fill-color: transparent;
29
+ background-clip: text;
30
+ margin: 40px 0;
31
+ user-select: none;
32
+ animation: pulse 2s ease-in-out infinite;
33
+ }
34
+
35
+ @keyframes pulse {
36
+ 0%, 100% {
37
+ opacity: 1;
38
+ }
39
+ 50% {
40
+ opacity: 0.8;
41
+ }
42
+ }
43
+
44
+ .counter-controls {
45
+ display: flex;
46
+ gap: 12px;
47
+ justify-content: center;
48
+ }
49
+
50
+ .counter-btn {
51
+ font-family: inherit;
52
+ font-size: 32px;
53
+ font-weight: 700;
54
+ width: 80px;
55
+ height: 80px;
56
+ border: none;
57
+ border-radius: 50%;
58
+ cursor: pointer;
59
+ transition: all 0.3s ease;
60
+ outline: none;
61
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
62
+ }
63
+
64
+ .counter-btn:hover:not(:disabled) {
65
+ transform: translateY(-3px);
66
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
67
+ }
68
+
69
+ .counter-btn:active:not(:disabled) {
70
+ transform: translateY(0);
71
+ }
72
+
73
+ .counter-btn:disabled {
74
+ opacity: 0.5;
75
+ cursor: not-allowed;
76
+ }
77
+
78
+ .counter-btn-increment {
79
+ background: linear-gradient(135deg, {{primaryColor}} 0%, {{secondaryColor}} 100%);
80
+ color: white;
81
+ }
82
+
83
+ .counter-btn-decrement {
84
+ background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 100%);
85
+ color: white;
86
+ }
87
+
88
+ .counter-btn-reset {
89
+ background: linear-gradient(135deg, #868e96 0%, #495057 100%);
90
+ color: white;
91
+ font-size: 16px;
92
+ }
93
+
94
+ /* Dark Mode Support */
95
+ @media (prefers-color-scheme: dark) {
96
+ .counter-container {
97
+ background: #2d3748;
98
+ }
99
+ }
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+ import Counter from './Counter';
3
+
4
+ /**
5
+ * Example usage of Counter component
6
+ */
7
+ const CounterExample = () => {
8
+ const handleChange = (value) => {
9
+ console.log('Counter value changed to:', value);
10
+ };
11
+
12
+ return (
13
+ <div style={{ padding: '40px' }}>
14
+ <h2 style={{ marginBottom: '40px', textAlign: 'center' }}>Counter Component Examples</h2>
15
+
16
+ <div style={{ display: 'grid', gap: '40px', gridTemplateColumns: 'repeat(auto-fit, minmax(400px, 1fr))' }}>
17
+ <div>
18
+ <h3 style={{ textAlign: 'center' }}>Basic Counter</h3>
19
+ <Counter onChange={handleChange} />
20
+ </div>
21
+
22
+ <div>
23
+ <h3 style={{ textAlign: 'center' }}>Counter with Limits</h3>
24
+ <Counter
25
+ initialValue={5}
26
+ min={0}
27
+ max={10}
28
+ onChange={handleChange}
29
+ />
30
+ </div>
31
+
32
+ <div>
33
+ <h3 style={{ textAlign: 'center' }}>Counter with Custom Step</h3>
34
+ <Counter
35
+ initialValue={0}
36
+ step={5}
37
+ onChange={handleChange}
38
+ />
39
+ </div>
40
+ </div>
41
+ </div>
42
+ );
43
+ };
44
+
45
+ export default CounterExample;
@@ -0,0 +1,70 @@
1
+ import React, { useState } from 'react';
2
+ import './Counter.css';
3
+
4
+ /**
5
+ * Counter Component
6
+ * A simple counter with increment and decrement functionality
7
+ */
8
+ const Counter = ({
9
+ initialValue = 0,
10
+ min,
11
+ max,
12
+ step = 1,
13
+ onChange
14
+ }) => {
15
+ const [count, setCount] = useState(initialValue);
16
+
17
+ const handleIncrement = () => {
18
+ const newValue = count + step;
19
+ if (max === undefined || newValue <= max) {
20
+ setCount(newValue);
21
+ onChange?.(newValue);
22
+ }
23
+ };
24
+
25
+ const handleDecrement = () => {
26
+ const newValue = count - step;
27
+ if (min === undefined || newValue >= min) {
28
+ setCount(newValue);
29
+ onChange?.(newValue);
30
+ }
31
+ };
32
+
33
+ const handleReset = () => {
34
+ setCount(initialValue);
35
+ onChange?.(initialValue);
36
+ };
37
+
38
+ return (
39
+ <div className="counter-container">
40
+ <h2 className="counter-title">Counter</h2>
41
+ <div className="counter-display">
42
+ {count}
43
+ </div>
44
+ <div className="counter-controls">
45
+ <button
46
+ className="counter-btn counter-btn-decrement"
47
+ onClick={handleDecrement}
48
+ disabled={min !== undefined && count <= min}
49
+ >
50
+ -
51
+ </button>
52
+ <button
53
+ className="counter-btn counter-btn-reset"
54
+ onClick={handleReset}
55
+ >
56
+ Reset
57
+ </button>
58
+ <button
59
+ className="counter-btn counter-btn-increment"
60
+ onClick={handleIncrement}
61
+ disabled={max !== undefined && count >= max}
62
+ >
63
+ +
64
+ </button>
65
+ </div>
66
+ </div>
67
+ );
68
+ };
69
+
70
+ export default Counter;
@@ -0,0 +1,128 @@
1
+ /* Form Styles */
2
+ .form-container {
3
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
4
+ background: white;
5
+ padding: 40px;
6
+ border-radius: 20px;
7
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
8
+ max-width: 500px;
9
+ margin: 0 auto;
10
+ }
11
+
12
+ .form-title {
13
+ font-size: 32px;
14
+ font-weight: 700;
15
+ margin: 0 0 30px 0;
16
+ text-align: center;
17
+ background: linear-gradient(135deg, {{primaryColor}} 0%, {{secondaryColor}} 100%);
18
+ -webkit-background-clip: text;
19
+ -webkit-text-fill-color: transparent;
20
+ background-clip: text;
21
+ }
22
+
23
+ .form {
24
+ display: flex;
25
+ flex-direction: column;
26
+ gap: 20px;
27
+ }
28
+
29
+ .form-group {
30
+ display: flex;
31
+ flex-direction: column;
32
+ gap: 8px;
33
+ }
34
+
35
+ .form-label {
36
+ font-size: 14px;
37
+ font-weight: 600;
38
+ color: #2d3748;
39
+ display: flex;
40
+ align-items: center;
41
+ gap: 4px;
42
+ }
43
+
44
+ .required {
45
+ color: #e53e3e;
46
+ }
47
+
48
+ .form input,
49
+ .form textarea,
50
+ .form select {
51
+ padding: 12px 16px;
52
+ font-size: 16px;
53
+ font-family: inherit;
54
+ border: 2px solid #e2e8f0;
55
+ border-radius: 8px;
56
+ transition: all 0.3s ease;
57
+ outline: none;
58
+ background: white;
59
+ }
60
+
61
+ .form input:focus,
62
+ .form textarea:focus,
63
+ .form select:focus {
64
+ border-color: {{primaryColor}};
65
+ box-shadow: 0 0 0 3px rgba(66, 153, 225, 0.1);
66
+ }
67
+
68
+ .form textarea {
69
+ resize: vertical;
70
+ min-height: 100px;
71
+ }
72
+
73
+ .form-error {
74
+ font-size: 14px;
75
+ color: #e53e3e;
76
+ display: flex;
77
+ align-items: center;
78
+ gap: 4px;
79
+ }
80
+
81
+ .form-submit {
82
+ margin-top: 10px;
83
+ padding: 16px 32px;
84
+ font-size: 16px;
85
+ font-weight: 600;
86
+ font-family: inherit;
87
+ background: linear-gradient(135deg, {{primaryColor}} 0%, {{secondaryColor}} 100%);
88
+ color: white;
89
+ border: none;
90
+ border-radius: 8px;
91
+ cursor: pointer;
92
+ transition: all 0.3s ease;
93
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
94
+ }
95
+
96
+ .form-submit:hover {
97
+ transform: translateY(-2px);
98
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
99
+ }
100
+
101
+ .form-submit:active {
102
+ transform: translateY(0);
103
+ }
104
+
105
+ /* Dark Mode Support */
106
+ @media (prefers-color-scheme: dark) {
107
+ .form-container {
108
+ background: #2d3748;
109
+ }
110
+
111
+ .form-label {
112
+ color: #e2e8f0;
113
+ }
114
+
115
+ .form input,
116
+ .form textarea,
117
+ .form select {
118
+ background: #1a202c;
119
+ color: #e2e8f0;
120
+ border-color: #4a5568;
121
+ }
122
+
123
+ .form input:focus,
124
+ .form textarea:focus,
125
+ .form select:focus {
126
+ border-color: {{primaryColor}};
127
+ }
128
+ }
@@ -0,0 +1,65 @@
1
+ import React from 'react';
2
+ import Form from './Form';
3
+
4
+ /**
5
+ * Example usage of Form component
6
+ */
7
+ const FormExample = () => {
8
+ const contactFields = [
9
+ {
10
+ name: 'name',
11
+ label: 'Full Name',
12
+ type: 'text',
13
+ required: true,
14
+ placeholder: 'John Doe',
15
+ minLength: 2
16
+ },
17
+ {
18
+ name: 'email',
19
+ label: 'Email Address',
20
+ type: 'email',
21
+ required: true,
22
+ placeholder: 'john@example.com',
23
+ pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
24
+ errorMessage: 'Please enter a valid email address'
25
+ },
26
+ {
27
+ name: 'subject',
28
+ label: 'Subject',
29
+ type: 'select',
30
+ required: true,
31
+ options: [
32
+ { value: 'general', label: 'General Inquiry' },
33
+ { value: 'support', label: 'Technical Support' },
34
+ { value: 'feedback', label: 'Feedback' }
35
+ ]
36
+ },
37
+ {
38
+ name: 'message',
39
+ label: 'Message',
40
+ type: 'textarea',
41
+ required: true,
42
+ placeholder: 'Type your message here...',
43
+ rows: 6,
44
+ minLength: 10
45
+ }
46
+ ];
47
+
48
+ const handleSubmit = (data) => {
49
+ console.log('Form submitted with data:', data);
50
+ alert('Form submitted successfully! Check console for details.');
51
+ };
52
+
53
+ return (
54
+ <div style={{ padding: '40px', maxWidth: '600px', margin: '0 auto' }}>
55
+ <Form
56
+ title="Contact Us"
57
+ fields={contactFields}
58
+ onSubmit={handleSubmit}
59
+ submitButtonText="Send Message"
60
+ />
61
+ </div>
62
+ );
63
+ };
64
+
65
+ export default FormExample;
@@ -0,0 +1,125 @@
1
+ import React, { useState } from 'react';
2
+ import './Form.css';
3
+
4
+ /**
5
+ * Form Component
6
+ * A flexible form component with validation
7
+ */
8
+ const Form = ({
9
+ title = 'Form',
10
+ fields = [],
11
+ onSubmit,
12
+ submitButtonText = 'Submit'
13
+ }) => {
14
+ const [formData, setFormData] = useState(() => {
15
+ const initialData = {};
16
+ fields.forEach(field => {
17
+ initialData[field.name] = field.defaultValue || '';
18
+ });
19
+ return initialData;
20
+ });
21
+
22
+ const [errors, setErrors] = useState({});
23
+
24
+ const handleChange = (e) => {
25
+ const { name, value, type, checked } = e.target;
26
+ setFormData(prev => ({
27
+ ...prev,
28
+ [name]: type === 'checkbox' ? checked : value
29
+ }));
30
+
31
+ // Clear error when user starts typing
32
+ if (errors[name]) {
33
+ setErrors(prev => ({ ...prev, [name]: '' }));
34
+ }
35
+ };
36
+
37
+ const validateField = (field, value) => {
38
+ if (field.required && !value) {
39
+ return `${field.label} is required`;
40
+ }
41
+
42
+ if (field.pattern && value && !field.pattern.test(value)) {
43
+ return field.errorMessage || `Invalid ${field.label.toLowerCase()}`;
44
+ }
45
+
46
+ if (field.minLength && value.length < field.minLength) {
47
+ return `${field.label} must be at least ${field.minLength} characters`;
48
+ }
49
+
50
+ return '';
51
+ };
52
+
53
+ const handleSubmit = (e) => {
54
+ e.preventDefault();
55
+
56
+ const newErrors = {};
57
+ fields.forEach(field => {
58
+ const error = validateField(field, formData[field.name]);
59
+ if (error) {
60
+ newErrors[field.name] = error;
61
+ }
62
+ });
63
+
64
+ if (Object.keys(newErrors).length > 0) {
65
+ setErrors(newErrors);
66
+ return;
67
+ }
68
+
69
+ onSubmit?.(formData);
70
+ };
71
+
72
+ const renderField = (field) => {
73
+ const commonProps = {
74
+ id: field.name,
75
+ name: field.name,
76
+ value: formData[field.name] || '',
77
+ onChange: handleChange,
78
+ required: field.required,
79
+ placeholder: field.placeholder
80
+ };
81
+
82
+ switch (field.type) {
83
+ case 'textarea':
84
+ return <textarea {...commonProps} rows={field.rows || 4} />;
85
+ case 'select':
86
+ return (
87
+ <select {...commonProps}>
88
+ <option value="">Select...</option>
89
+ {field.options?.map(option => (
90
+ <option key={option.value} value={option.value}>
91
+ {option.label}
92
+ </option>
93
+ ))}
94
+ </select>
95
+ );
96
+ default:
97
+ return <input type={field.type || 'text'} {...commonProps} />;
98
+ }
99
+ };
100
+
101
+ return (
102
+ <div className="form-container">
103
+ <h2 className="form-title">{title}</h2>
104
+ <form onSubmit={handleSubmit} className="form">
105
+ {fields.map(field => (
106
+ <div key={field.name} className="form-group">
107
+ <label htmlFor={field.name} className="form-label">
108
+ {field.label}
109
+ {field.required && <span className="required">*</span>}
110
+ </label>
111
+ {renderField(field)}
112
+ {errors[field.name] && (
113
+ <span className="form-error">{errors[field.name]}</span>
114
+ )}
115
+ </div>
116
+ ))}
117
+ <button type="submit" className="form-submit">
118
+ {submitButtonText}
119
+ </button>
120
+ </form>
121
+ </div>
122
+ );
123
+ };
124
+
125
+ export default Form;
@@ -0,0 +1,152 @@
1
+ /* Modal Styles */
2
+ .modal-overlay {
3
+ position: fixed;
4
+ top: 0;
5
+ left: 0;
6
+ right: 0;
7
+ bottom: 0;
8
+ background: rgba(0, 0, 0, 0.6);
9
+ display: flex;
10
+ align-items: center;
11
+ justify-content: center;
12
+ z-index: 1000;
13
+ animation: fadeIn 0.3s ease;
14
+ backdrop-filter: blur(4px);
15
+ }
16
+
17
+ @keyframes fadeIn {
18
+ from {
19
+ opacity: 0;
20
+ }
21
+ to {
22
+ opacity: 1;
23
+ }
24
+ }
25
+
26
+ .modal-content {
27
+ background: white;
28
+ border-radius: 16px;
29
+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
30
+ max-height: 90vh;
31
+ display: flex;
32
+ flex-direction: column;
33
+ animation: slideUp 0.3s ease;
34
+ overflow: hidden;
35
+ }
36
+
37
+ @keyframes slideUp {
38
+ from {
39
+ transform: translateY(30px);
40
+ opacity: 0;
41
+ }
42
+ to {
43
+ transform: translateY(0);
44
+ opacity: 1;
45
+ }
46
+ }
47
+
48
+ .modal-small {
49
+ width: 90%;
50
+ max-width: 400px;
51
+ }
52
+
53
+ .modal-medium {
54
+ width: 90%;
55
+ max-width: 600px;
56
+ }
57
+
58
+ .modal-large {
59
+ width: 90%;
60
+ max-width: 900px;
61
+ }
62
+
63
+ .modal-header {
64
+ padding: 24px 32px;
65
+ border-bottom: 1px solid #e2e8f0;
66
+ display: flex;
67
+ align-items: center;
68
+ justify-content: space-between;
69
+ background: linear-gradient(135deg, {{primaryColor}}15 0%, {{secondaryColor}}15 100%);
70
+ }
71
+
72
+ .modal-title {
73
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
74
+ font-size: 24px;
75
+ font-weight: 700;
76
+ margin: 0;
77
+ background: linear-gradient(135deg, {{primaryColor}} 0%, {{secondaryColor}} 100%);
78
+ -webkit-background-clip: text;
79
+ -webkit-text-fill-color: transparent;
80
+ background-clip: text;
81
+ }
82
+
83
+ .modal-close {
84
+ font-size: 36px;
85
+ font-weight: 300;
86
+ background: none;
87
+ border: none;
88
+ cursor: pointer;
89
+ color: #718096;
90
+ padding: 0;
91
+ width: 36px;
92
+ height: 36px;
93
+ display: flex;
94
+ align-items: center;
95
+ justify-content: center;
96
+ border-radius: 50%;
97
+ transition: all 0.2s ease;
98
+ line-height: 1;
99
+ }
100
+
101
+ .modal-close:hover {
102
+ background: #f7fafc;
103
+ color: #2d3748;
104
+ }
105
+
106
+ .modal-body {
107
+ padding: 32px;
108
+ overflow-y: auto;
109
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
110
+ font-size: 16px;
111
+ line-height: 1.6;
112
+ color: #2d3748;
113
+ }
114
+
115
+ .modal-footer {
116
+ padding: 20px 32px;
117
+ border-top: 1px solid #e2e8f0;
118
+ display: flex;
119
+ gap: 12px;
120
+ justify-content: flex-end;
121
+ background: #f7fafc;
122
+ }
123
+
124
+ /* Dark Mode Support */
125
+ @media (prefers-color-scheme: dark) {
126
+ .modal-content {
127
+ background: #2d3748;
128
+ }
129
+
130
+ .modal-header {
131
+ border-bottom-color: #4a5568;
132
+ background: linear-gradient(135deg, {{primaryColor}}20 0%, {{secondaryColor}}20 100%);
133
+ }
134
+
135
+ .modal-body {
136
+ color: #e2e8f0;
137
+ }
138
+
139
+ .modal-footer {
140
+ background: #1a202c;
141
+ border-top-color: #4a5568;
142
+ }
143
+
144
+ .modal-close {
145
+ color: #cbd5e0;
146
+ }
147
+
148
+ .modal-close:hover {
149
+ background: #4a5568;
150
+ color: #e2e8f0;
151
+ }
152
+ }