Skip to content

Commit db3c384

Browse files
feat: Add support for theming (#10)
1 parent 4a3d29c commit db3c384

File tree

16 files changed

+795
-266
lines changed

16 files changed

+795
-266
lines changed

src/App.css

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
.app {
2+
min-height: 100vh;
3+
display: flex;
4+
flex-direction: column;
5+
}
6+
7+
.app-header {
8+
padding: 1rem;
9+
display: flex;
10+
justify-content: space-between;
11+
align-items: center;
12+
border-bottom: 1px solid;
13+
}
14+
15+
.app-header h1 {
16+
margin: 0;
17+
font-size: 1.5rem;
18+
}
19+
20+
.theme-toggle {
21+
padding: 0.5rem 1rem;
22+
border: 1px solid;
23+
border-radius: 4px;
24+
cursor: pointer;
25+
font-size: 1rem;
26+
transition: opacity 0.2s;
27+
}
28+
29+
.theme-toggle:hover {
30+
opacity: 0.9;
31+
}
32+
33+
.app-content {
34+
flex: 1;
35+
padding: 1rem;
36+
}
37+
38+
.table-container {
39+
border-radius: 4px;
40+
overflow: hidden;
41+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
42+
}

src/App.tsx

Lines changed: 100 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1+
import React, { useState } from "react";
2+
13
import { MultiLevelTable } from "./components/MultiLevelTable";
4+
import { darkTheme, lightTheme } from "./themes";
5+
import type { ThemeProps } from "./types/theme";
6+
import type { Column, DataItem } from "./types/types";
7+
8+
import "./App.css";
29

3-
const data = [
10+
const data: DataItem[] = [
411
{
512
id: 1,
613
name: "Parent 1",
@@ -357,75 +364,103 @@ const data = [
357364
},
358365
];
359366

360-
const columns = [
361-
{
362-
key: "name",
363-
title: "Name",
364-
filterable: true,
365-
},
366-
{
367-
key: "value",
368-
title: "Value",
369-
render: (value: unknown) => `$${value as number}`,
370-
filterable: true,
371-
},
372-
{
373-
key: "status",
374-
title: "Status",
375-
filterable: true,
376-
sortable: true,
377-
customSortFn: (rowA: any, rowB: any, columnId: string) => {
378-
const statusOrder = { 'Active': 0, 'Pending': 1, 'Inactive': 2 };
379-
const statusA = String(rowA[columnId]);
380-
const statusB = String(rowB[columnId]);
381-
382-
return (statusOrder[statusA as keyof typeof statusOrder] || 0) - (statusOrder[statusB as keyof typeof statusOrder] || 0);
367+
const StatusCell: React.FC<{ value: string; theme: ThemeProps }> = ({
368+
value,
369+
}) => {
370+
return (
371+
<span
372+
style={{
373+
padding: "4px 8px",
374+
borderRadius: "4px",
375+
backgroundColor: "#ffffff",
376+
color:
377+
value === "Active"
378+
? "#2ecc71"
379+
: value === "Inactive"
380+
? "#e74c3c"
381+
: "#f1c40f",
382+
}}
383+
>
384+
{value}
385+
</span>
386+
);
387+
};
388+
389+
const App: React.FC = () => {
390+
const [isDarkMode, setIsDarkMode] = useState(false);
391+
const theme = isDarkMode ? darkTheme : lightTheme;
392+
393+
const toggleTheme = () => {
394+
setIsDarkMode((prev) => !prev);
395+
};
396+
397+
const columns: Column[] = [
398+
{
399+
key: "name",
400+
title: "Name",
401+
filterable: true,
383402
},
384-
render: (value: unknown) => (
385-
<span
386-
style={{
387-
padding: "4px 8px",
388-
borderRadius: "4px",
389-
backgroundColor:
390-
value === "Active"
391-
? "#e6ffe6"
392-
: value === "Inactive"
393-
? "#ffe6e6"
394-
: "#fff2e6",
395-
color:
396-
value === "Active"
397-
? "#006600"
398-
: value === "Inactive"
399-
? "#cc0000"
400-
: "#cc7700",
401-
}}
402-
>
403-
{value as string}
404-
</span>
405-
),
406-
},
407-
];
403+
{
404+
key: "value",
405+
title: "Value",
406+
filterable: true,
407+
render: (value: string | number) => `$${value}`,
408+
},
409+
{
410+
key: "status",
411+
title: "Status",
412+
filterable: true,
413+
render: (value: string | number) => (
414+
<StatusCell value={value as string} theme={theme} />
415+
),
416+
},
417+
];
408418

409-
const renderCustomPagination = () => {
410-
return <div>Custom Pagination </div>;
411-
};
419+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
420+
const renderCustomPagination = () => {
421+
return <div>Custom Pagination </div>;
422+
};
412423

413-
function App() {
414424
return (
415-
<div style={{ padding: "20px", maxWidth: "1200px", margin: "0 auto" }}>
416-
<h1>React Multi Level Table Demo</h1>
417-
<p>Features: Sorting, Filtering, Pagination, and Nested Data</p>
418-
<MultiLevelTable
419-
data={data}
420-
columns={columns}
421-
pageSize={5}
422-
sortable={true}
423-
ascendingIcon={<div></div>}
424-
descendingIcon={<div></div>}
425-
renderCustomPagination={renderCustomPagination}
426-
/>
425+
<div className="app" style={{ backgroundColor: theme.colors?.background }}>
426+
<header
427+
className="app-header"
428+
style={{ backgroundColor: theme.table?.header?.background }}
429+
>
430+
<h1 style={{ color: theme.table?.header?.textColor }}>
431+
Multi-Level Table Demo
432+
</h1>
433+
<button
434+
className="theme-toggle"
435+
onClick={toggleTheme}
436+
style={{
437+
backgroundColor: theme.colors?.primaryColor,
438+
color: "#ffffff",
439+
borderColor: theme.colors?.borderColor,
440+
}}
441+
>
442+
{isDarkMode ? "☀️ Light Mode" : "🌙 Dark Mode"}
443+
</button>
444+
</header>
445+
446+
<main className="app-content">
447+
<div
448+
className="table-container"
449+
style={{ backgroundColor: theme.colors?.background }}
450+
>
451+
<MultiLevelTable
452+
data={data}
453+
columns={columns}
454+
theme={theme}
455+
pageSize={5}
456+
sortable={true}
457+
ascendingIcon={<div></div>}
458+
descendingIcon={<div></div>}
459+
/>
460+
</div>
461+
</main>
427462
</div>
428463
);
429-
}
464+
};
430465

431466
export default App;

src/components/ExpandIcon.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import React from 'react';
2+
3+
import type { ThemeProps } from '../types/theme';
24
import '../styles/ExpandIcon.css';
35

46
/**
57
* Props for the ExpandIcon component
68
* @interface ExpandIconProps
79
* @property {boolean} isExpanded - Whether the row is expanded
10+
* @property {ThemeProps} theme - The theme object
811
*/
912
interface ExpandIconProps {
1013
isExpanded: boolean;
14+
theme: ThemeProps;
1115
}
1216

1317
/**
@@ -16,8 +20,10 @@ interface ExpandIconProps {
1620
* @param {ExpandIconProps} props - Component props
1721
* @returns {JSX.Element} Rendered expand/collapse icon
1822
*/
19-
export const ExpandIcon: React.FC<ExpandIconProps> = ({ isExpanded }) => (
20-
<span className="expand-icon">
21-
{isExpanded ? '▼' : '▶'}
22-
</span>
23-
);
23+
export const ExpandIcon: React.FC<ExpandIconProps> = ({ isExpanded, theme }) => {
24+
return (
25+
<span className="expand-icon" style={{ color: theme.expandIcon?.color }}>
26+
{isExpanded ? '▼' : '▶'}
27+
</span>
28+
);
29+
};

0 commit comments

Comments
 (0)