Skip to content

Commit dd6c445

Browse files
committed
feat: enhance accessibility by adding labels to input fields across various components
1 parent d5d4dcc commit dd6c445

File tree

13 files changed

+106
-43
lines changed

13 files changed

+106
-43
lines changed

.github/copilot-instructions.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
Dear Copilot,
2+
3+
## Project Overview
4+
5+
BottleCRM is a dynamic, SaaS CRM platform designed to streamline the entire CRM needs of startups and enterprises. Built with modern web technologies, it offers a seamless experience for users through robust role-based access control (RBAC). Each user role is equipped with tailored functionalities to enhance efficiency, engagement, and management, ensuring a streamlined and secure business process.
6+
7+
user types we have
8+
9+
- Org
10+
- user(s)
11+
- Admin
12+
- super admin - anyone with @micropyramid.com email to manage whole platform
13+
14+
## Project Context
15+
16+
BottleCRM is a modern CRM application built with:
17+
- **Framework**: SvelteKit 2.21.x, Svelte 5.x, Prisma
18+
- **Styling**: tailwind 4.1.x css
19+
- **Database**: postgresql
20+
- **Icons**: fontawesome, we are migrating to lucide icons
21+
22+
## Important Notes
23+
- We need to ensure access control is strictly enforced based on user roles. No record is accessible unless the user or the org has the appropriate permissions.
24+
- When implementing forms in sveltekit A form label must be associated with a control

.vscode/settings.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,16 @@
88
"[svelte]": {
99
"editor.tabSize": 2,
1010
"editor.insertSpaces": true
11-
}
11+
},
12+
"github.copilot.chat.codeGeneration.instructions": [
13+
{
14+
"file": "prisma/schema.prisma",
15+
},
16+
{
17+
"file": "src/hooks.server.js",
18+
},
19+
{
20+
"file": "src/lib/prisma.js",
21+
},
22+
]
1223
}

src/routes/(admin)/+layout.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,10 @@
101101
<!-- Mobile search -->
102102
<div class="pt-2">
103103
<div class="relative">
104+
<label for="admin-search" class="sr-only">Search</label>
104105
<Search class="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-gray-400" />
105106
<input
107+
id="admin-search"
106108
type="text"
107109
placeholder="Search..."
108110
class="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent text-sm"

src/routes/(admin)/admin/blogs/[id]/edit/+page.svelte

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -92,55 +92,60 @@
9292
<input type="hidden" name="title" value={editable_title} />
9393
<input type="hidden" name="slug" value={slug} />
9494
<div>
95-
<label class="block font-medium mb-1">
95+
<label for="blog-title" class="block font-medium mb-1">
9696
Title:
97-
<input
98-
bind:value={editable_title}
99-
required
100-
class="mt-1 block w-full rounded border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500"
101-
/>
10297
</label>
98+
<input
99+
id="blog-title"
100+
bind:value={editable_title}
101+
required
102+
class="mt-1 block w-full rounded border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500"
103+
/>
103104
</div>
104105
<div>
105-
<label class="block font-medium mb-1">
106+
<label for="blog-seo-title" class="block font-medium mb-1">
106107
SEO Title:
107-
<input
108-
name="seoTitle"
109-
bind:value={blog.seoTitle}
110-
class="mt-1 block w-full rounded border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500"
111-
/>
112108
</label>
109+
<input
110+
id="blog-seo-title"
111+
name="seoTitle"
112+
bind:value={blog.seoTitle}
113+
class="mt-1 block w-full rounded border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500"
114+
/>
113115
</div>
114116
<div>
115-
<label class="block font-medium mb-1">
117+
<label for="blog-seo-description" class="block font-medium mb-1">
116118
SEO Description:
117-
<textarea
118-
name="seoDescription"
119-
bind:value={blog.seoDescription}
120-
class="mt-1 block w-full rounded border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500"
121-
></textarea>
122119
</label>
120+
<textarea
121+
id="blog-seo-description"
122+
name="seoDescription"
123+
bind:value={blog.seoDescription}
124+
class="mt-1 block w-full rounded border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500"
125+
></textarea>
123126
</div>
124127
<div>
125-
<label class="block font-medium mb-1">
128+
<label for="blog-excerpt" class="block font-medium mb-1">
126129
Excerpt:
127-
<textarea
128-
name="excerpt"
129-
bind:value={blog.excerpt}
130-
class="mt-1 block w-full rounded border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500"
131-
></textarea>
132130
</label>
131+
<textarea
132+
id="blog-excerpt"
133+
name="excerpt"
134+
bind:value={blog.excerpt}
135+
class="mt-1 block w-full rounded border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500"
136+
></textarea>
133137
</div>
134138
<div>
135-
<label class="block font-medium mb-1">
139+
<label for="blog-slug" class="block font-medium mb-1">
136140
Slug:
137-
<input
138-
bind:value={slug}
139-
required
140-
class="mt-1 block w-full rounded border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500"
141-
disabled={!blog.draft}
142-
/>
143141
</label>
142+
<input
143+
id="blog-slug"
144+
bind:value={slug}
145+
required
146+
class="mt-1 block w-full rounded border-gray-300 shadow-sm focus:ring-blue-500 focus:border-blue-500"
147+
disabled={!blog.draft}
148+
/>
144149
{#if !blog.draft}
145150
<p class="text-xs text-gray-500 mt-1">
146151
Slug can only be edited in draft mode.

src/routes/(app)/app/accounts/+page.svelte

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,11 @@
9999
<div class="flex flex-col sm:flex-row gap-3">
100100
<!-- Search -->
101101
<div class="relative">
102+
<label for="accounts-search" class="sr-only">Search accounts</label>
102103
<Search class="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
103104
<input
104105
type="text"
106+
id="accounts-search"
105107
placeholder="Search accounts..."
106108
class="pl-10 pr-4 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg text-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent min-w-[250px]"
107109
bind:value={searchQuery}
@@ -111,8 +113,10 @@
111113

112114
<!-- Status Filter -->
113115
<div class="relative">
116+
<label for="accounts-status-filter" class="sr-only">Filter accounts by status</label>
114117
<Filter class="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-4 h-4" />
115118
<select
119+
id="accounts-status-filter"
116120
class="pl-10 pr-8 py-2.5 border border-gray-300 dark:border-gray-600 rounded-lg text-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-blue-500 appearance-none min-w-[120px]"
117121
bind:value={statusFilter}
118122
onchange={updateQueryParams}

src/routes/(app)/app/invoices/+page.svelte

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99
<!-- Search -->
1010
<div class="flex-1 flex items-center bg-white/80 backdrop-blur-md rounded-xl shadow px-4 py-2 border border-blue-200">
1111
<svg class="w-5 h-5 text-blue-400 mr-2" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
12-
<input type="text" placeholder="Search invoices..." class="bg-transparent outline-none flex-1 text-blue-900 placeholder-blue-400" />
12+
<label for="invoice-search" class="sr-only">Search invoices</label>
13+
<input id="invoice-search" type="text" placeholder="Search invoices..." class="bg-transparent outline-none flex-1 text-blue-900 placeholder-blue-400" />
1314
</div>
1415
<!-- Status Filter -->
1516
<div class="flex items-center bg-white/80 backdrop-blur-md rounded-xl shadow px-4 py-2 border border-blue-200">
1617
<svg class="w-5 h-5 text-purple-400 mr-2" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><rect x="3" y="7" width="18" height="13" rx="2"/><path d="M16 3v4M8 3v4"/></svg>
17-
<select class="bg-transparent outline-none text-blue-900 font-semibold">
18+
<label for="invoice-status-filter" class="sr-only">Filter by status</label>
19+
<select id="invoice-status-filter" class="bg-transparent outline-none text-blue-900 font-semibold">
1820
<option>All Statuses</option>
1921
<option>Paid</option>
2022
<option>Unpaid</option>
@@ -24,7 +26,8 @@
2426
<!-- Date Range -->
2527
<div class="flex items-center bg-white/80 backdrop-blur-md rounded-xl shadow px-4 py-2 border border-blue-200">
2628
<svg class="w-5 h-5 text-blue-400 mr-2" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2"/><path d="M16 2v4M8 2v4M3 10h18"/></svg>
27-
<input type="text" placeholder="Date range" class="bg-transparent outline-none text-blue-900 placeholder-blue-400 w-28" />
29+
<label for="invoice-date-range" class="sr-only">Date range filter</label>
30+
<input id="invoice-date-range" type="text" placeholder="Date range" class="bg-transparent outline-none text-blue-900 placeholder-blue-400 w-28" />
2831
</div>
2932
</div>
3033
<div class="flex flex-col gap-5">

src/routes/(app)/app/leads/open/+page.svelte

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,10 @@
196196
<!-- Search and Filter Toggle -->
197197
<div class="flex flex-col sm:flex-row gap-4 mb-4">
198198
<div class="flex-1 relative">
199+
<label for="lead-search" class="sr-only">Search leads</label>
199200
<Search class="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400 dark:text-gray-500" />
200201
<input
202+
id="lead-search"
201203
type="text"
202204
placeholder="Search by name, company, or email..."
203205
bind:value={searchQuery}
@@ -222,24 +224,24 @@
222224
{#if showFilters}
223225
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 p-4 bg-gray-50 dark:bg-gray-700 rounded-lg" transition:fade>
224226
<div>
225-
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Status</label>
226-
<select bind:value={statusFilter} class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:focus:ring-blue-400 dark:focus:border-blue-400 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100">
227+
<label for="status-filter" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Status</label>
228+
<select id="status-filter" bind:value={statusFilter} class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:focus:ring-blue-400 dark:focus:border-blue-400 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100">
227229
{#each statuses as status}
228230
<option value={status.value}>{status.label}</option>
229231
{/each}
230232
</select>
231233
</div>
232234
<div>
233-
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Source</label>
234-
<select bind:value={sourceFilter} class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:focus:ring-blue-400 dark:focus:border-blue-400 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100">
235+
<label for="source-filter" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Source</label>
236+
<select id="source-filter" bind:value={sourceFilter} class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:focus:ring-blue-400 dark:focus:border-blue-400 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100">
235237
{#each sources as source}
236238
<option value={source.value}>{source.label}</option>
237239
{/each}
238240
</select>
239241
</div>
240242
<div>
241-
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Rating</label>
242-
<select bind:value={ratingFilter} class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:focus:ring-blue-400 dark:focus:border-blue-400 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100">
243+
<label for="rating-filter" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Rating</label>
244+
<select id="rating-filter" bind:value={ratingFilter} class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:focus:ring-blue-400 dark:focus:border-blue-400 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100">
243245
{#each ratings as rating}
244246
<option value={rating.value}>{rating.label}</option>
245247
{/each}

src/routes/(app)/app/opportunities/+page.svelte

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,13 @@
203203
<!-- Search -->
204204
<div class="flex-1">
205205
<div class="relative">
206+
<label for="opportunities-search" class="sr-only">Search opportunities</label>
206207
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
207208
<Search class="h-5 w-5 text-gray-400" />
208209
</div>
209210
<input
210211
type="text"
212+
id="opportunities-search"
211213
bind:value={searchTerm}
212214
placeholder="Search opportunities, accounts, or owners..."
213215
class="block w-full pl-10 pr-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md leading-5 bg-white dark:bg-gray-700 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400 focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500"
@@ -217,7 +219,9 @@
217219
218220
<!-- Stage Filter -->
219221
<div class="sm:w-48">
222+
<label for="opportunities-stage-filter" class="sr-only">Filter opportunities by stage</label>
220223
<select
224+
id="opportunities-stage-filter"
221225
bind:value={selectedStage}
222226
class="block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500"
223227
>

src/routes/(app)/app/tasks/+page.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
{/if}
1818
<form class="board-card board-create" method="POST" action="?/create">
1919
<div class="plus-icon">+</div>
20-
<input name="name" placeholder="New board name" required />
20+
<label for="board-name" class="sr-only">Board name</label>
21+
<input id="board-name" name="name" placeholder="New board name" required />
2122
<button type="submit">Create Board</button>
2223
</form>
2324
</div>

src/routes/(app)/app/users/+page.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,9 @@
309309
{#if user.editingRole}
310310
<form method="POST" action="?/edit_role" class="flex items-center gap-2">
311311
<input type="hidden" name="user_id" value={user.id} />
312+
<label for="role-select-{user.id}" class="sr-only">User Role</label>
312313
<select
314+
id="role-select-{user.id}"
313315
name="role"
314316
class="rounded-lg border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-white text-xs focus:border-blue-500 dark:focus:border-blue-400 focus:ring-blue-500 dark:focus:ring-blue-400"
315317
>

0 commit comments

Comments
 (0)