Skip to content

Commit ca3503a

Browse files
committed
feat(styles): add tailwind and font management system
- Add Tailwind CSS directives to global.css - Update tailwind config to include CSS files - Create fonts.css for centralized font management - Implement font loading detection in Layout - Apply consistent text sizing across components
1 parent 4b9b9e6 commit ca3503a

File tree

6 files changed

+109
-24
lines changed

6 files changed

+109
-24
lines changed

src/components/Home.astro

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const categories = ['All', ...new Set(tools.map((tool) => tool.category))];
6161
type="text"
6262
id="searchInput"
6363
placeholder="Search tools..."
64-
class="w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-xl py-3 pl-12 pr-4 text-gray-700 dark:text-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 focus:border-transparent hover:border-gray-400 dark:hover:border-gray-600 transition-all duration-250 h-12 box-border"
64+
class="w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-xl py-3 pl-12 pr-4 text-gray-700 dark:text-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 focus:border-transparent hover:border-gray-400 dark:hover:border-gray-600 transition-all duration-250 h-12 box-border text-base leading-normal"
6565
aria-label="Search for tools"
6666
autocomplete="off"
6767
/>
@@ -74,11 +74,11 @@ const categories = ['All', ...new Set(tools.map((tool) => tool.category))];
7474
<div class="relative w-full sm:w-64 group">
7575
<select
7676
id="categoryFilter"
77-
class="appearance-none w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-xl py-3 pl-12 pr-10 text-gray-700 dark:text-gray-200 cursor-pointer focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 focus:border-transparent hover:border-gray-400 dark:hover:border-gray-600 transition-all duration-250 font-medium h-12 box-border"
77+
class="appearance-none w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded-xl py-3 pl-12 pr-10 text-gray-700 dark:text-gray-200 cursor-pointer focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 focus:border-transparent hover:border-gray-400 dark:hover:border-gray-600 transition-all duration-250 font-medium h-12 box-border text-base leading-normal"
7878
aria-label="Filter tools by category"
7979
>
8080
{categories.map(category => (
81-
<option value={category} class="py-2 font-medium dark:bg-gray-800">{category}</option>
81+
<option value={category} class="py-2 font-medium dark:bg-gray-800 text-base leading-normal">{category}</option>
8282
))}
8383
</select>
8484
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-4 text-gray-500 dark:text-gray-400 transition-all duration-250">
@@ -101,11 +101,11 @@ const categories = ['All', ...new Set(tools.map((tool) => tool.category))];
101101
<table class="min-w-full divide-y divide-gray-200" role="grid" aria-label="Frontend tools list">
102102
<thead class="bg-gray-100 dark:bg-gray-700">
103103
<tr>
104-
<th scope="col" class="px-4 sm:px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">Icon</th>
105-
<th scope="col" class="px-4 sm:px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">Name</th>
106-
<th scope="col" class="px-4 sm:px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider hidden md:table-cell">Description</th>
107-
<th scope="col" class="px-4 sm:px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider hidden sm:table-cell">Category</th>
108-
<th scope="col" class="px-4 sm:px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">Links</th>
104+
<th scope="col" class="px-4 sm:px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider text-base leading-normal">Icon</th>
105+
<th scope="col" class="px-4 sm:px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider text-base leading-normal">Name</th>
106+
<th scope="col" class="px-4 sm:px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider hidden md:table-cell text-base leading-normal">Description</th>
107+
<th scope="col" class="px-4 sm:px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider hidden sm:table-cell text-base leading-normal">Category</th>
108+
<th scope="col" class="px-4 sm:px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider text-base leading-normal">Links</th>
109109
</tr>
110110
</thead>
111111
<tbody id="toolsTableBody" class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700 [&>tr]:h-[72px] [&>tr:nth-child(even)]:bg-gray-50 dark:[&>tr:nth-child(even)]:bg-gray-700/50">
@@ -404,16 +404,16 @@ const categories = ['All', ...new Set(tools.map((tool) => tool.category))];
404404
</script>
405405

406406
<style is:global>
407-
/* Import Inter font for UI */
408-
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
409-
/* Import Rubik for headings */
410-
@import url('https://fonts.googleapis.com/css2?family=Rubik:wght@400;500;600;700&display=swap');
411-
412-
.font-inter {
413-
font-family: 'Inter', system-ui, -apple-system, sans-serif;
407+
/* Font classes moved to src/styles/fonts.css */
408+
/* Additional component-specific styles can be added here */
409+
410+
/* Apply consistent sizing to elements */
411+
.table th {
412+
@apply text-base leading-normal;
414413
}
415-
416-
.font-rubik {
417-
font-family: 'Rubik', system-ui, -apple-system, sans-serif;
414+
415+
/* Ensure consistent sizing for important text elements */
416+
.tool-name {
417+
@apply text-base leading-normal;
418418
}
419419
</style>

src/components/ToolCard.astro

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,14 @@ const images = import.meta.glob<{ default: ImageMetadata }>('/src/assets/icons/*
6767
</div>
6868
</td>
6969
<td class="px-4 sm:px-6 py-4 whitespace-nowrap">
70-
<div class="text-sm font-medium" style="color: var(--color-text);" transition:name={`tool-name-${name}`}>{name}</div>
70+
<div class="text-sm font-medium text-base leading-normal tool-name" style="color: var(--color-text);" transition:name={`tool-name-${name}`}>{name}</div>
7171
</td>
7272
<td class="px-4 sm:px-6 py-4 whitespace-normal hidden md:table-cell h-[72px]">
73-
<div class="text-sm line-clamp-2" style="color: var(--color-text-secondary);">{description}</div>
73+
<div class="text-sm line-clamp-2 text-base leading-normal" style="color: var(--color-text-secondary);">{description}</div>
7474
</td>
7575
<td class="px-4 sm:px-6 py-4 whitespace-nowrap hidden sm:table-cell">
7676
<span
77-
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full"
77+
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full text-base leading-normal"
7878
style="
7979
background-color: rgba(var(--color-primary-rgb), 0.1);
8080
color: var(--color-primary);
@@ -90,7 +90,7 @@ const images = import.meta.glob<{ default: ImageMetadata }>('/src/assets/icons/*
9090
href={docsLink}
9191
target="_blank"
9292
rel="noopener noreferrer"
93-
class="group inline-flex items-center px-3 py-1 rounded-full text-sm gap-1 w-full sm:w-auto justify-center transition-colors duration-200"
93+
class="group inline-flex items-center px-3 py-1 rounded-full text-sm gap-1 w-full sm:w-auto justify-center transition-colors duration-200 text-base leading-normal"
9494
style="
9595
background-color: rgba(var(--color-primary-rgb), 0.1);
9696
color: var(--color-primary);
@@ -111,7 +111,7 @@ const images = import.meta.glob<{ default: ImageMetadata }>('/src/assets/icons/*
111111
href={githubLink}
112112
target="_blank"
113113
rel="noopener noreferrer"
114-
class="group inline-flex items-center px-3 py-1 rounded-full text-sm gap-1 w-full sm:w-auto justify-center transition-colors duration-200"
114+
class="group inline-flex items-center px-3 py-1 rounded-full text-sm gap-1 w-full sm:w-auto justify-center transition-colors duration-200 text-base leading-normal"
115115
style="
116116
background-color: rgba(var(--color-text-rgb, 31, 41, 55), 0.1);
117117
color: var(--color-text-secondary);

src/layouts/Layout.astro

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { ClientRouter } from 'astro:transitions';
33
import Header from '../components/Header.astro';
44
import { BRAND_NAME } from '../constants/brand';
55
import '../styles/global.css';
6+
import '../styles/fonts.css';
67
78
interface Props {
89
title?: string;
@@ -186,12 +187,60 @@ const {
186187
});
187188
});
188189

190+
// Font loading detection
191+
const detectFontLoading = () => {
192+
// Add fonts-loading class to document during loading
193+
document.documentElement.classList.add('fonts-loading');
194+
195+
// Use Font Face Observer pattern
196+
const fontLoadPromises = [
197+
new Promise(resolve => {
198+
// Check if Inter font is loaded
199+
if (document.fonts) {
200+
document.fonts.ready.then(() => {
201+
// Mark fonts as loaded
202+
document.documentElement.classList.remove('fonts-loading');
203+
document.documentElement.classList.add('fonts-loaded');
204+
resolve();
205+
});
206+
} else {
207+
// Fallback for browsers without document.fonts
208+
setTimeout(() => {
209+
document.documentElement.classList.remove('fonts-loading');
210+
document.documentElement.classList.add('fonts-loaded');
211+
resolve();
212+
}, 300);
213+
}
214+
})
215+
];
216+
217+
// When all fonts are loaded
218+
Promise.all(fontLoadPromises).then(() => {
219+
console.log('All fonts loaded successfully');
220+
}).catch(err => {
221+
console.warn('Font loading issue:', err);
222+
// Still mark as loaded to prevent UI being stuck
223+
document.documentElement.classList.remove('fonts-loading');
224+
document.documentElement.classList.add('fonts-loaded');
225+
});
226+
};
227+
228+
// Initialize font loading detection
229+
if (document.readyState === 'loading') {
230+
document.addEventListener('DOMContentLoaded', detectFontLoading);
231+
} else {
232+
detectFontLoading();
233+
}
234+
189235
document.addEventListener('astro:page-load', () => {
190236
// Reset loading state immediately
191237
requestAnimationFrame(() => {
192238
document.documentElement.classList.remove('astro-loading', 'astro-loading-done');
193239
});
194240

241+
// Re-detect fonts on page navigation
242+
detectFontLoading();
243+
195244
// Announce page changes to screen readers
196245
const pageTitle = document.title;
197246
const announcer = document.getElementById('announcer') || document.createElement('div');

src/styles/fonts.css

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* Font management for the application */
2+
3+
/* Font loading strategy */
4+
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap&text=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.,;:?!@#$%^&*()_+-=[]{}|<>/~`\'"&display=swap');
5+
@import url('https://fonts.googleapis.com/css2?family=Rubik:wght@400;500;600;700&display=swap&text=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.,;:?!@#$%^&*()_+-=[]{}|<>/~`\'"&display=swap');
6+
7+
/* Font classes */
8+
.font-inter {
9+
font-family: 'Inter', system-ui, -apple-system, sans-serif;
10+
font-display: swap;
11+
}
12+
13+
.font-rubik {
14+
font-family: 'Rubik', system-ui, -apple-system, sans-serif;
15+
font-display: swap;
16+
}
17+
18+
/* Font loading state classes */
19+
.fonts-loading {
20+
/* Prevent layout shifts during font loading */
21+
font-size: calc(1rem);
22+
letter-spacing: normal;
23+
}
24+
25+
.fonts-loaded {
26+
/* Apply final font styling once fonts are loaded */
27+
font-size: calc(1rem);
28+
letter-spacing: normal;
29+
transition: letter-spacing 0.1s ease-out;
30+
}

src/styles/global.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
/* Global styles */
2+
@tailwind base;
3+
@tailwind components;
4+
@tailwind utilities;
25

36
/* Base styles */
47
html {

tailwind.config.mjs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
/** @type {import('tailwindcss').Config} */
22
export default {
3-
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
3+
content: [
4+
'./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}',
5+
'./src/styles/**/*.css'
6+
],
47
darkMode: 'class',
58
theme: {
69
extend: {},

0 commit comments

Comments
 (0)