@classic-homes/theme-styles 0.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.
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@classic-homes/theme-styles",
3
+ "version": "0.1.0",
4
+ "description": "Base styles and utilities for the Classic Theme design system",
5
+ "type": "module",
6
+ "scripts": {
7
+ "build": "echo 'No build needed for styles package'"
8
+ },
9
+ "exports": {
10
+ ".": "./src/index.css",
11
+ "./base": "./src/base.css",
12
+ "./accessibility": "./src/accessibility.css",
13
+ "./utilities": "./src/utilities.css"
14
+ },
15
+ "files": [
16
+ "src"
17
+ ],
18
+ "keywords": [
19
+ "styles",
20
+ "css",
21
+ "design-system",
22
+ "classic-theme"
23
+ ],
24
+ "license": "MIT",
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/Classic-Homes/classic-theme.git",
28
+ "directory": "packages/styles"
29
+ },
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "peerDependencies": {
34
+ "@classic-homes/theme-tokens": "*"
35
+ }
36
+ }
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Classic Theme Accessibility Styles
3
+ *
4
+ * WCAG 2.1 AA compliant styles for focus states, touch targets,
5
+ * reduced motion, and screen reader utilities.
6
+ */
7
+
8
+ @layer classic-theme.base {
9
+ /* ===== Focus Visible Styles (WCAG 2.4.7) ===== */
10
+
11
+ /* Default focus ring using brand primary color */
12
+ :focus-visible {
13
+ outline: 2px solid hsl(var(--ring));
14
+ outline-offset: 2px;
15
+ }
16
+
17
+ /* Remove default outline for mouse users (handled by :focus-visible) */
18
+ :focus:not(:focus-visible) {
19
+ outline: none;
20
+ }
21
+
22
+ /* Enhanced focus for interactive elements */
23
+ button:focus-visible,
24
+ [role='button']:focus-visible,
25
+ input:focus-visible,
26
+ select:focus-visible,
27
+ textarea:focus-visible,
28
+ a:focus-visible {
29
+ outline: 2px solid hsl(var(--ring));
30
+ outline-offset: 2px;
31
+ border-radius: var(--radius, 0.25rem);
32
+ }
33
+
34
+ /* ===== Skip Link (WCAG 2.4.1) ===== */
35
+
36
+ .skip-link {
37
+ position: absolute;
38
+ top: -100%;
39
+ left: 0;
40
+ background-color: hsl(var(--primary));
41
+ color: hsl(var(--primary-foreground));
42
+ padding: 0.75rem 1rem;
43
+ z-index: 9999;
44
+ font-weight: 600;
45
+ text-decoration: none;
46
+ border-radius: 0 0 var(--radius) 0;
47
+ }
48
+
49
+ .skip-link:focus {
50
+ top: 0;
51
+ outline: none;
52
+ }
53
+
54
+ /* ===== Touch Target Utilities (WCAG 2.5.5) ===== */
55
+
56
+ /* Minimum 44x44px touch targets for mobile */
57
+ .touch-target {
58
+ min-width: 44px;
59
+ min-height: 44px;
60
+ }
61
+
62
+ /* Expanded touch area using pseudo-element */
63
+ .touch-target-expand {
64
+ position: relative;
65
+ }
66
+
67
+ .touch-target-expand::after {
68
+ content: '';
69
+ position: absolute;
70
+ top: 50%;
71
+ left: 50%;
72
+ transform: translate(-50%, -50%);
73
+ min-width: 44px;
74
+ min-height: 44px;
75
+ width: 100%;
76
+ height: 100%;
77
+ }
78
+
79
+ /* ===== Reduced Motion (WCAG 2.3.3) ===== */
80
+
81
+ @media (prefers-reduced-motion: reduce) {
82
+ *,
83
+ *::before,
84
+ *::after {
85
+ animation-duration: 0.01ms !important;
86
+ animation-iteration-count: 1 !important;
87
+ transition-duration: 0.01ms !important;
88
+ scroll-behavior: auto !important;
89
+ }
90
+ }
91
+
92
+ /* ===== Screen Reader Only (WCAG) ===== */
93
+
94
+ .sr-only {
95
+ position: absolute;
96
+ width: 1px;
97
+ height: 1px;
98
+ padding: 0;
99
+ margin: -1px;
100
+ overflow: hidden;
101
+ clip: rect(0, 0, 0, 0);
102
+ white-space: nowrap;
103
+ border-width: 0;
104
+ }
105
+
106
+ /* Show element when focused (for skip links) */
107
+ .sr-only-focusable:focus,
108
+ .sr-only-focusable:active {
109
+ position: static;
110
+ width: auto;
111
+ height: auto;
112
+ padding: inherit;
113
+ margin: inherit;
114
+ overflow: visible;
115
+ clip: auto;
116
+ white-space: normal;
117
+ }
118
+
119
+ /* ===== High Contrast Mode Support ===== */
120
+
121
+ @media (forced-colors: active) {
122
+ /* Ensure borders are visible in high contrast mode */
123
+ button,
124
+ input,
125
+ select,
126
+ textarea,
127
+ [role='button'] {
128
+ border: 1px solid ButtonText;
129
+ }
130
+
131
+ /* Ensure focus is visible */
132
+ :focus-visible {
133
+ outline: 2px solid Highlight;
134
+ }
135
+ }
136
+
137
+ /* ===== Visible Focus Indicator Utility ===== */
138
+
139
+ .focus-ring {
140
+ outline: none;
141
+ }
142
+
143
+ .focus-ring:focus-visible {
144
+ box-shadow:
145
+ 0 0 0 2px hsl(var(--background)),
146
+ 0 0 0 4px hsl(var(--ring));
147
+ }
148
+
149
+ /* ===== Not Focusable Utility ===== */
150
+
151
+ .not-focusable {
152
+ outline: none !important;
153
+ box-shadow: none !important;
154
+ }
155
+
156
+ .not-focusable:focus {
157
+ outline: none !important;
158
+ }
159
+ }
package/src/base.css ADDED
@@ -0,0 +1,205 @@
1
+ /**
2
+ * Classic Theme Base Styles
3
+ *
4
+ * Provides foundational typography and base element styles
5
+ * following Classic Homes brand guidelines.
6
+ */
7
+
8
+ @layer classic-theme.base {
9
+ /* Import brand fonts from Google Fonts */
10
+ @import url('https://fonts.googleapis.com/css2?family=Figtree:wght@300;400;500;600;700;900&family=Source+Serif+4:opsz,wght@8..60,400;8..60,600;8..60,700&display=swap');
11
+
12
+ /* Base HTML setup */
13
+ html {
14
+ font-family: var(
15
+ --font-sans,
16
+ 'Figtree',
17
+ ui-sans-serif,
18
+ system-ui,
19
+ -apple-system,
20
+ BlinkMacSystemFont,
21
+ 'Segoe UI',
22
+ Roboto,
23
+ 'Helvetica Neue',
24
+ Arial,
25
+ sans-serif
26
+ );
27
+ font-size: 16px;
28
+ line-height: 1.5;
29
+ -webkit-font-smoothing: antialiased;
30
+ -moz-osx-font-smoothing: grayscale;
31
+ }
32
+
33
+ /* Body base styles */
34
+ body {
35
+ color: hsl(var(--foreground));
36
+ background-color: hsl(var(--background));
37
+ margin: 0;
38
+ min-height: 100vh;
39
+ }
40
+
41
+ /* Heading styles - use serif font per brand guidelines */
42
+ h1,
43
+ h2,
44
+ h3,
45
+ h4,
46
+ h5,
47
+ h6 {
48
+ font-family: var(
49
+ --font-serif,
50
+ 'Source Serif 4',
51
+ ui-serif,
52
+ Georgia,
53
+ Cambria,
54
+ 'Times New Roman',
55
+ Times,
56
+ serif
57
+ );
58
+ color: hsl(var(--foreground));
59
+ font-weight: 600;
60
+ line-height: 1.2;
61
+ margin-top: 0;
62
+ margin-bottom: 0.5em;
63
+ }
64
+
65
+ h1 {
66
+ font-size: 2.25rem;
67
+ } /* 36px */
68
+ h2 {
69
+ font-size: 1.875rem;
70
+ } /* 30px */
71
+ h3 {
72
+ font-size: 1.5rem;
73
+ } /* 24px */
74
+ h4 {
75
+ font-size: 1.25rem;
76
+ } /* 20px */
77
+ h5 {
78
+ font-size: 1.125rem;
79
+ } /* 18px */
80
+ h6 {
81
+ font-size: 1rem;
82
+ } /* 16px */
83
+
84
+ /* Paragraph and text */
85
+ p {
86
+ margin-top: 0;
87
+ margin-bottom: 1rem;
88
+ }
89
+
90
+ /* Links */
91
+ a {
92
+ color: hsl(var(--primary));
93
+ text-decoration: none;
94
+ transition: color 0.2s ease;
95
+ }
96
+
97
+ a:hover {
98
+ text-decoration: underline;
99
+ }
100
+
101
+ /* Strong text */
102
+ strong,
103
+ b {
104
+ font-weight: 600;
105
+ }
106
+
107
+ /* Code elements */
108
+ code,
109
+ kbd,
110
+ pre,
111
+ samp {
112
+ font-family:
113
+ ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New',
114
+ monospace;
115
+ font-size: 0.875em;
116
+ }
117
+
118
+ code {
119
+ background-color: hsl(var(--muted));
120
+ padding: 0.125rem 0.25rem;
121
+ border-radius: 0.25rem;
122
+ }
123
+
124
+ pre {
125
+ background-color: hsl(var(--muted));
126
+ padding: 1rem;
127
+ border-radius: var(--radius);
128
+ overflow-x: auto;
129
+ }
130
+
131
+ pre code {
132
+ background-color: transparent;
133
+ padding: 0;
134
+ }
135
+
136
+ /* Lists */
137
+ ul,
138
+ ol {
139
+ margin-top: 0;
140
+ margin-bottom: 1rem;
141
+ padding-left: 1.5rem;
142
+ }
143
+
144
+ li {
145
+ margin-bottom: 0.25rem;
146
+ }
147
+
148
+ /* Horizontal rule */
149
+ hr {
150
+ border: 0;
151
+ border-top: 1px solid hsl(var(--border));
152
+ margin: 1.5rem 0;
153
+ }
154
+
155
+ /* Images */
156
+ img {
157
+ max-width: 100%;
158
+ height: auto;
159
+ display: block;
160
+ }
161
+
162
+ /* Tables */
163
+ table {
164
+ border-collapse: collapse;
165
+ width: 100%;
166
+ margin-bottom: 1rem;
167
+ }
168
+
169
+ th,
170
+ td {
171
+ padding: 0.75rem;
172
+ text-align: left;
173
+ border-bottom: 1px solid hsl(var(--border));
174
+ }
175
+
176
+ th {
177
+ font-weight: 600;
178
+ background-color: hsl(var(--muted));
179
+ }
180
+
181
+ /* Form element resets */
182
+ button,
183
+ input,
184
+ select,
185
+ textarea {
186
+ font-family: inherit;
187
+ font-size: inherit;
188
+ line-height: inherit;
189
+ }
190
+
191
+ /* Blockquote */
192
+ blockquote {
193
+ border-left: 4px solid hsl(var(--primary));
194
+ margin: 1rem 0;
195
+ padding-left: 1rem;
196
+ color: hsl(var(--muted-foreground));
197
+ font-style: italic;
198
+ }
199
+
200
+ /* Selection styles */
201
+ ::selection {
202
+ background-color: hsl(var(--primary) / 0.2);
203
+ color: hsl(var(--foreground));
204
+ }
205
+ }
package/src/index.css ADDED
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Classic Theme Styles
3
+ *
4
+ * Main entry point for all Classic Theme styles.
5
+ * Import this file in your app.css before Tailwind directives:
6
+ *
7
+ * @import '@classic-theme/styles';
8
+ * @tailwind base;
9
+ * @tailwind components;
10
+ * @tailwind utilities;
11
+ */
12
+
13
+ /* Define CSS layer order - lowest to highest specificity */
14
+ @layer classic-theme.tokens, classic-theme.base, classic-theme.components, classic-theme.utilities;
15
+
16
+ /* Import design tokens (CSS custom properties) */
17
+ @import '@classic-theme/tokens/css';
18
+
19
+ /* Import base styles */
20
+ @import './base.css';
21
+
22
+ /* Import accessibility styles */
23
+ @import './accessibility.css';
24
+
25
+ /* Import utility classes */
26
+ @import './utilities.css';
@@ -0,0 +1,260 @@
1
+ /**
2
+ * Classic Theme Utility Styles
3
+ *
4
+ * Common utility classes for scrollbars, transitions,
5
+ * and other frequently needed styles.
6
+ */
7
+
8
+ @layer classic-theme.utilities {
9
+ /* ===== Scrollbar Utilities ===== */
10
+
11
+ /* Hide scrollbar but keep functionality */
12
+ .scrollbar-hide {
13
+ -ms-overflow-style: none; /* IE and Edge */
14
+ scrollbar-width: none; /* Firefox */
15
+ }
16
+
17
+ .scrollbar-hide::-webkit-scrollbar {
18
+ display: none; /* Chrome, Safari, Opera */
19
+ }
20
+
21
+ /* Thin scrollbar */
22
+ .scrollbar-thin {
23
+ scrollbar-width: thin;
24
+ scrollbar-color: hsl(var(--muted-foreground) / 0.3) transparent;
25
+ }
26
+
27
+ .scrollbar-thin::-webkit-scrollbar {
28
+ width: 6px;
29
+ height: 6px;
30
+ }
31
+
32
+ .scrollbar-thin::-webkit-scrollbar-track {
33
+ background: transparent;
34
+ }
35
+
36
+ .scrollbar-thin::-webkit-scrollbar-thumb {
37
+ background-color: hsl(var(--muted-foreground) / 0.3);
38
+ border-radius: 3px;
39
+ }
40
+
41
+ .scrollbar-thin::-webkit-scrollbar-thumb:hover {
42
+ background-color: hsl(var(--muted-foreground) / 0.5);
43
+ }
44
+
45
+ /* ===== Transition Utilities ===== */
46
+
47
+ .transition-colors {
48
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
49
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
50
+ transition-duration: 150ms;
51
+ }
52
+
53
+ .transition-opacity {
54
+ transition-property: opacity;
55
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
56
+ transition-duration: 150ms;
57
+ }
58
+
59
+ .transition-transform {
60
+ transition-property: transform;
61
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
62
+ transition-duration: 150ms;
63
+ }
64
+
65
+ .transition-all {
66
+ transition-property: all;
67
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
68
+ transition-duration: 150ms;
69
+ }
70
+
71
+ /* Menu item transition (for sidebar/nav items) */
72
+ .transition-menu-item {
73
+ transition:
74
+ background-color 150ms ease,
75
+ color 150ms ease,
76
+ transform 100ms ease;
77
+ }
78
+
79
+ /* ===== Text Utilities ===== */
80
+
81
+ /* Truncate single line */
82
+ .truncate {
83
+ overflow: hidden;
84
+ text-overflow: ellipsis;
85
+ white-space: nowrap;
86
+ }
87
+
88
+ /* Line clamp utilities */
89
+ .line-clamp-1 {
90
+ display: -webkit-box;
91
+ -webkit-line-clamp: 1;
92
+ -webkit-box-orient: vertical;
93
+ overflow: hidden;
94
+ }
95
+
96
+ .line-clamp-2 {
97
+ display: -webkit-box;
98
+ -webkit-line-clamp: 2;
99
+ -webkit-box-orient: vertical;
100
+ overflow: hidden;
101
+ }
102
+
103
+ .line-clamp-3 {
104
+ display: -webkit-box;
105
+ -webkit-line-clamp: 3;
106
+ -webkit-box-orient: vertical;
107
+ overflow: hidden;
108
+ }
109
+
110
+ /* ===== Layout Utilities ===== */
111
+
112
+ /* Container with max-width and padding */
113
+ .container-default {
114
+ width: 100%;
115
+ margin-left: auto;
116
+ margin-right: auto;
117
+ padding-left: 1rem;
118
+ padding-right: 1rem;
119
+ }
120
+
121
+ @media (min-width: 640px) {
122
+ .container-default {
123
+ max-width: 640px;
124
+ }
125
+ }
126
+
127
+ @media (min-width: 768px) {
128
+ .container-default {
129
+ max-width: 768px;
130
+ }
131
+ }
132
+
133
+ @media (min-width: 1024px) {
134
+ .container-default {
135
+ max-width: 1024px;
136
+ }
137
+ }
138
+
139
+ @media (min-width: 1280px) {
140
+ .container-default {
141
+ max-width: 1280px;
142
+ }
143
+ }
144
+
145
+ /* ===== Interactive State Utilities ===== */
146
+
147
+ /* Disabled state */
148
+ .disabled {
149
+ pointer-events: none;
150
+ opacity: 0.5;
151
+ cursor: not-allowed;
152
+ }
153
+
154
+ /* Interactive hover */
155
+ .hover-lift {
156
+ transition:
157
+ transform 150ms ease,
158
+ box-shadow 150ms ease;
159
+ }
160
+
161
+ .hover-lift:hover {
162
+ transform: translateY(-2px);
163
+ box-shadow:
164
+ 0 4px 6px -1px rgb(0 0 0 / 0.1),
165
+ 0 2px 4px -2px rgb(0 0 0 / 0.1);
166
+ }
167
+
168
+ /* ===== Animation Utilities ===== */
169
+
170
+ /* Spin animation */
171
+ @keyframes spin {
172
+ from {
173
+ transform: rotate(0deg);
174
+ }
175
+ to {
176
+ transform: rotate(360deg);
177
+ }
178
+ }
179
+
180
+ .animate-spin {
181
+ animation: spin 1s linear infinite;
182
+ }
183
+
184
+ .animate-spin-slow {
185
+ animation: spin 2s linear infinite;
186
+ }
187
+
188
+ /* Pulse animation */
189
+ @keyframes pulse {
190
+ 0%,
191
+ 100% {
192
+ opacity: 1;
193
+ }
194
+ 50% {
195
+ opacity: 0.5;
196
+ }
197
+ }
198
+
199
+ .animate-pulse {
200
+ animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
201
+ }
202
+
203
+ /* Fade in animation */
204
+ @keyframes fade-in {
205
+ from {
206
+ opacity: 0;
207
+ }
208
+ to {
209
+ opacity: 1;
210
+ }
211
+ }
212
+
213
+ .animate-fade-in {
214
+ animation: fade-in 200ms ease-out;
215
+ }
216
+
217
+ /* Slide up animation */
218
+ @keyframes slide-up {
219
+ from {
220
+ opacity: 0;
221
+ transform: translateY(10px);
222
+ }
223
+ to {
224
+ opacity: 1;
225
+ transform: translateY(0);
226
+ }
227
+ }
228
+
229
+ .animate-slide-up {
230
+ animation: slide-up 200ms ease-out;
231
+ }
232
+
233
+ /* Slide down animation */
234
+ @keyframes slide-down {
235
+ from {
236
+ opacity: 0;
237
+ transform: translateY(-10px);
238
+ }
239
+ to {
240
+ opacity: 1;
241
+ transform: translateY(0);
242
+ }
243
+ }
244
+
245
+ .animate-slide-down {
246
+ animation: slide-down 200ms ease-out;
247
+ }
248
+
249
+ /* ===== Print Utilities ===== */
250
+
251
+ @media print {
252
+ .print-hidden {
253
+ display: none !important;
254
+ }
255
+
256
+ .print-visible {
257
+ display: block !important;
258
+ }
259
+ }
260
+ }