Skip to content

Commit 1b39148

Browse files
committed
Critique on table
1 parent df154f3 commit 1b39148

4 files changed

Lines changed: 482 additions & 35 deletions

File tree

src/components/Table/Table.module.scss

Lines changed: 102 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
@use '../../styles/mixins' as *;
22

3+
/* --- Screen reader only --- */
4+
5+
.srOnly {
6+
@include sr-only;
7+
}
8+
9+
/* --- Wrapper --- */
10+
311
.wrapper {
412
display: flex;
513
flex-direction: column;
@@ -50,7 +58,7 @@
5058

5159
.thead {
5260
border-bottom: 2px solid var(--table-accent, var(--color-border));
53-
background-color: var(--table-header-bg, transparent);
61+
background-color: var(--table-header-bg, var(--color-surface));
5462
color: var(--table-header-color, inherit);
5563
}
5664

@@ -89,24 +97,40 @@
8997
}
9098

9199
.sortIcon {
92-
font-size: var(--font-size-xs);
93-
line-height: 1;
94-
opacity: 0.6;
100+
display: inline-flex;
101+
align-items: center;
102+
flex-shrink: 0;
95103
}
96104

105+
/* Resize handle — 8px hit target centered on the column boundary */
106+
97107
.resizeHandle {
98108
position: absolute;
99109
right: 0;
100110
top: 0;
101111
bottom: 0;
102-
width: 4px;
112+
width: 8px;
103113
cursor: col-resize;
104114
background: transparent;
115+
border: none;
116+
padding: 0;
105117

106-
&:hover,
107-
&:active {
118+
/* Visible indicator line */
119+
&::after {
120+
content: '';
121+
position: absolute;
122+
right: 3px;
123+
top: 20%;
124+
bottom: 20%;
125+
width: 2px;
126+
border-radius: 1px;
127+
background: var(--color-border);
128+
transition: background-color var(--transition-fast);
129+
}
130+
131+
&:hover::after,
132+
&:active::after {
108133
background: var(--color-primary);
109-
opacity: 0.3;
110134
}
111135
}
112136

@@ -133,6 +157,25 @@
133157
color: var(--color-text-secondary);
134158
}
135159

160+
/* Inline "Clear search" link inside the empty state */
161+
162+
.clearSearchButton {
163+
background: none;
164+
border: none;
165+
padding: 0;
166+
color: var(--color-primary);
167+
cursor: pointer;
168+
font: inherit;
169+
text-decoration: underline;
170+
text-underline-offset: 2px;
171+
172+
@include focus-ring;
173+
174+
&:hover {
175+
color: var(--color-primary-hover);
176+
}
177+
}
178+
136179
.selectable {
137180
cursor: pointer;
138181
}
@@ -141,6 +184,48 @@
141184
background-color: color-mix(in srgb, var(--table-accent, var(--color-primary)) 12%, transparent) !important;
142185
}
143186

187+
/* Focus ring on selectable rows */
188+
189+
.selectable:focus-visible {
190+
outline: var(--focus-ring-width) solid var(--focus-ring-color);
191+
outline-offset: -2px;
192+
}
193+
194+
/* --- Skeleton loading --- */
195+
196+
@keyframes skeleton-shimmer {
197+
0% {
198+
background-position: -200% 0;
199+
}
200+
201+
100% {
202+
background-position: 200% 0;
203+
}
204+
}
205+
206+
.skeletonRow {
207+
pointer-events: none;
208+
}
209+
210+
.skeletonCell {
211+
display: block;
212+
height: 1rem;
213+
border-radius: var(--radius-sm);
214+
background: linear-gradient(
215+
90deg,
216+
var(--color-surface) 25%,
217+
var(--color-border) 50%,
218+
var(--color-surface) 75%
219+
);
220+
background-size: 200% 100%;
221+
animation: skeleton-shimmer 1.5s ease-in-out infinite;
222+
223+
@include reduced-motion {
224+
animation: none;
225+
background: var(--color-surface);
226+
}
227+
}
228+
144229
/* --- Striping --- */
145230

146231
.stripedRows .tbody .tr:nth-child(even) {
@@ -170,14 +255,15 @@
170255
.pagination {
171256
display: flex;
172257
align-items: center;
173-
justify-content: center;
258+
justify-content: space-between;
174259
gap: var(--space-4);
175260
padding: var(--space-2) 0;
176261
}
177262

178263
.pageButton {
179264
display: inline-flex;
180265
align-items: center;
266+
gap: var(--space-1);
181267
border: 1px solid var(--color-border);
182268
border-radius: var(--radius-md);
183269
background: transparent;
@@ -204,7 +290,14 @@
204290
}
205291

206292
.pageInfo {
293+
display: flex;
294+
align-items: center;
295+
gap: var(--space-2);
207296
font-size: var(--font-size-sm);
208297
color: var(--color-text-secondary);
209298
}
210299

300+
.showingInfo {
301+
color: var(--color-text-secondary);
302+
}
303+

src/components/Table/Table.stories.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const meta: Meta<typeof Table> = {
3434
headerColor: { control: 'color' },
3535
headerTextColor: { control: 'color' },
3636
selectable: { control: 'boolean' },
37+
loading: { control: 'boolean' },
3738
},
3839
};
3940

@@ -98,7 +99,7 @@ export const ColoredHeader: Story = {
9899
},
99100
};
100101

101-
/** Selectable rows — click a row to highlight it. */
102+
/** Selectable rows — click or press Enter/Space to select; click again or press Escape to deselect. */
102103
export const SelectableRows: Story = {
103104
args: {
104105
columns,
@@ -108,6 +109,25 @@ export const SelectableRows: Story = {
108109
},
109110
};
110111

112+
/** Loading skeleton — shown while data is being fetched. */
113+
export const Loading: Story = {
114+
args: {
115+
columns,
116+
data: [],
117+
loading: true,
118+
pageSize: 5,
119+
},
120+
};
121+
122+
/** Error state — displayed when data could not be loaded. */
123+
export const ErrorState: Story = {
124+
args: {
125+
columns,
126+
data: [],
127+
error: 'Failed to load users. Please try again.',
128+
},
129+
};
130+
111131
/** Full-featured table with header color, selectable rows, search, pagination. */
112132
export const KitchenSink: Story = {
113133
args: {
@@ -125,3 +145,4 @@ export const KitchenSink: Story = {
125145
},
126146
};
127147

148+

0 commit comments

Comments
 (0)