@a11ypros/a11y-ui-components 1.0.4 → 1.0.5
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/dist/components/Accordion/Accordion.css +117 -0
- package/dist/components/Accordion/Accordion.d.ts +76 -0
- package/dist/components/Accordion/Accordion.d.ts.map +1 -0
- package/dist/components/Accordion/Accordion.js +91 -0
- package/dist/components/Accordion/index.d.ts +3 -0
- package/dist/components/Accordion/index.d.ts.map +1 -0
- package/dist/components/Accordion/index.js +1 -0
- package/dist/components/Button/Button.css +3 -2
- package/dist/components/DataTable/DataTable.d.ts +5 -1
- package/dist/components/DataTable/DataTable.d.ts.map +1 -1
- package/dist/components/DataTable/DataTable.js +2 -2
- package/dist/components/Link/Link.css +2 -2
- package/dist/components/Modal/Modal.css +1 -0
- package/dist/components/Modal/Modal.d.ts +4 -0
- package/dist/components/Modal/Modal.d.ts.map +1 -1
- package/dist/components/Modal/Modal.js +2 -2
- package/dist/components/Tabs/Tabs.css +6 -6
- package/dist/components/Tabs/Tabs.d.ts +4 -0
- package/dist/components/Tabs/Tabs.d.ts.map +1 -1
- package/dist/components/Tabs/Tabs.js +2 -2
- package/dist/components/Toast/Toast.d.ts +4 -0
- package/dist/components/Toast/Toast.d.ts.map +1 -1
- package/dist/components/Toast/Toast.js +2 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/styles/global.css +75 -3
- package/package.json +1 -1
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/* Accordion container */
|
|
2
|
+
.accordion {
|
|
3
|
+
display: flex;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
gap: var(--spacing-2, 0.5rem);
|
|
6
|
+
width: 100%;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/* Accordion item (details element) */
|
|
10
|
+
.accordion-item {
|
|
11
|
+
background-color: var(--color-background-default, #ffffff);
|
|
12
|
+
border: 1px solid var(--color-border-default, #e5e5e5);
|
|
13
|
+
border-radius: 0.5rem;
|
|
14
|
+
transition: border-color var(--motion-duration-normal, 200ms) var(--motion-easing-ease-out, cubic-bezier(0, 0, 0.2, 1));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.accordion-item:hover {
|
|
18
|
+
border-color: var(--color-border-hover, #d4d4d4);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* Respect reduced motion */
|
|
22
|
+
@media (prefers-reduced-motion: reduce) {
|
|
23
|
+
.accordion-item {
|
|
24
|
+
transition: none;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* Accordion summary (clickable header) */
|
|
29
|
+
.accordion-item__summary {
|
|
30
|
+
display: flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
justify-content: space-between;
|
|
33
|
+
gap: var(--spacing-3, 0.75rem);
|
|
34
|
+
padding: var(--spacing-4, 1rem);
|
|
35
|
+
cursor: pointer;
|
|
36
|
+
list-style: none;
|
|
37
|
+
user-select: none;
|
|
38
|
+
font-weight: var(--font-weight-medium, 500);
|
|
39
|
+
color: var(--color-text-primary, #171717);
|
|
40
|
+
transition: background-color var(--motion-duration-normal, 200ms) var(--motion-easing-ease-out, cubic-bezier(0, 0, 0.2, 1));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* Remove default marker */
|
|
44
|
+
.accordion-item__summary::-webkit-details-marker {
|
|
45
|
+
display: none;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.accordion-item__summary::marker {
|
|
49
|
+
display: none;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.accordion-item__summary:hover {
|
|
53
|
+
background-color: var(--color-background-secondary, #fafafa);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* Focus styles - WCAG 2.4.7 Focus Visible */
|
|
57
|
+
.accordion-item__summary:focus-visible {
|
|
58
|
+
outline: 2px solid var(--color-border-focus, #0ea5e9);
|
|
59
|
+
outline-offset: -2px;
|
|
60
|
+
border-radius: 0.5rem;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.accordion-item__summary:focus:not(:focus-visible) {
|
|
64
|
+
outline: none;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* High contrast mode support */
|
|
68
|
+
@media (prefers-contrast: high) {
|
|
69
|
+
.accordion-item {
|
|
70
|
+
border-width: 2px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.accordion-item__summary:focus-visible {
|
|
74
|
+
outline-width: 3px;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/* Title text */
|
|
79
|
+
.accordion-item__title {
|
|
80
|
+
flex: 1;
|
|
81
|
+
text-align: left;
|
|
82
|
+
font-size: var(--font-size-base, 1rem);
|
|
83
|
+
line-height: var(--line-height-normal, 1.5);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* Chevron icon */
|
|
87
|
+
.accordion-item__icon {
|
|
88
|
+
flex-shrink: 0;
|
|
89
|
+
width: 1.25rem;
|
|
90
|
+
height: 1.25rem;
|
|
91
|
+
color: var(--color-text-secondary, #737373);
|
|
92
|
+
transition: transform var(--motion-duration-normal, 200ms) var(--motion-easing-ease-out, cubic-bezier(0, 0, 0.2, 1));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/* Rotate icon when open */
|
|
96
|
+
.accordion-item[open] .accordion-item__icon {
|
|
97
|
+
transform: rotate(180deg);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* Respect reduced motion */
|
|
101
|
+
@media (prefers-reduced-motion: reduce) {
|
|
102
|
+
.accordion-item__icon {
|
|
103
|
+
transition: none;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.accordion-item[open] .accordion-item__icon {
|
|
107
|
+
transform: none;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* Content area */
|
|
112
|
+
.accordion-item__content {
|
|
113
|
+
padding: 0 var(--spacing-4, 1rem) var(--spacing-4, 1rem);
|
|
114
|
+
color: var(--color-text-secondary, #525252);
|
|
115
|
+
font-size: var(--font-size-base, 1rem);
|
|
116
|
+
line-height: var(--line-height-relaxed, 1.625);
|
|
117
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import './Accordion.css';
|
|
3
|
+
export interface AccordionItemProps {
|
|
4
|
+
/**
|
|
5
|
+
* Unique identifier for the accordion item
|
|
6
|
+
*/
|
|
7
|
+
id: string;
|
|
8
|
+
/**
|
|
9
|
+
* Title/header of the accordion item
|
|
10
|
+
*/
|
|
11
|
+
title: string;
|
|
12
|
+
/**
|
|
13
|
+
* Content of the accordion item
|
|
14
|
+
*/
|
|
15
|
+
children: React.ReactNode;
|
|
16
|
+
/**
|
|
17
|
+
* Whether the item is initially open
|
|
18
|
+
*/
|
|
19
|
+
defaultOpen?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Custom class name for the item
|
|
22
|
+
*/
|
|
23
|
+
className?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Accessible Accordion Item component using native HTML5 details/summary
|
|
27
|
+
*
|
|
28
|
+
* WCAG Compliance:
|
|
29
|
+
* - 2.1.1 Keyboard: Full keyboard support (Enter/Space)
|
|
30
|
+
* - 2.4.7 Focus Visible: Clear focus indicators
|
|
31
|
+
* - 4.1.2 Name, Role, Value: Semantic HTML elements
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```tsx
|
|
35
|
+
* <AccordionItem id="item-1" title="Section 1">
|
|
36
|
+
* <p>Content for section 1</p>
|
|
37
|
+
* </AccordionItem>
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare const AccordionItem: React.ForwardRefExoticComponent<AccordionItemProps & React.RefAttributes<HTMLDetailsElement>>;
|
|
41
|
+
export interface AccordionProps {
|
|
42
|
+
/**
|
|
43
|
+
* Accordion items (AccordionItem components)
|
|
44
|
+
*/
|
|
45
|
+
children: React.ReactNode;
|
|
46
|
+
/**
|
|
47
|
+
* Whether to allow multiple items to be open at once
|
|
48
|
+
*/
|
|
49
|
+
allowMultiple?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Custom class name
|
|
52
|
+
*/
|
|
53
|
+
className?: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Accessible Accordion container component
|
|
57
|
+
*
|
|
58
|
+
* WCAG Compliance:
|
|
59
|
+
* - 2.1.1 Keyboard: Full keyboard navigation support
|
|
60
|
+
* - 2.4.7 Focus Visible: Clear focus indicators on all interactive elements
|
|
61
|
+
* - 4.1.2 Name, Role, Value: Semantic HTML with proper structure
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```tsx
|
|
65
|
+
* <Accordion>
|
|
66
|
+
* <AccordionItem id="item-1" title="First Item">
|
|
67
|
+
* <p>Content 1</p>
|
|
68
|
+
* </AccordionItem>
|
|
69
|
+
* <AccordionItem id="item-2" title="Second Item">
|
|
70
|
+
* <p>Content 2</p>
|
|
71
|
+
* </AccordionItem>
|
|
72
|
+
* </Accordion>
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export declare const Accordion: React.ForwardRefExoticComponent<AccordionProps & React.RefAttributes<HTMLDivElement>>;
|
|
76
|
+
//# sourceMappingURL=Accordion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Accordion.d.ts","sourceRoot":"","sources":["../../../src/components/Accordion/Accordion.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,iBAAiB,CAAA;AAExB,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,EAAE,EAAE,MAAM,CAAA;IAEV;;OAEG;IACH,KAAK,EAAE,MAAM,CAAA;IAEb;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IAEzB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IAErB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,aAAa,+FA8DzB,CAAA;AAID,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IAEzB;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IAEvB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,SAAS,uFAyDrB,CAAA"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { createActivationHandler } from '../../utils/keyboard';
|
|
5
|
+
import './Accordion.css';
|
|
6
|
+
/**
|
|
7
|
+
* Accessible Accordion Item component using native HTML5 details/summary
|
|
8
|
+
*
|
|
9
|
+
* WCAG Compliance:
|
|
10
|
+
* - 2.1.1 Keyboard: Full keyboard support (Enter/Space)
|
|
11
|
+
* - 2.4.7 Focus Visible: Clear focus indicators
|
|
12
|
+
* - 4.1.2 Name, Role, Value: Semantic HTML elements
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* <AccordionItem id="item-1" title="Section 1">
|
|
17
|
+
* <p>Content for section 1</p>
|
|
18
|
+
* </AccordionItem>
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export const AccordionItem = React.forwardRef(({ id, title, children, defaultOpen = false, className = '', ...props }, ref) => {
|
|
22
|
+
const handleSummaryKeyDown = (event) => {
|
|
23
|
+
// Ensure Enter and Space work consistently
|
|
24
|
+
const activationHandler = createActivationHandler(() => {
|
|
25
|
+
const details = event.currentTarget.parentElement;
|
|
26
|
+
if (details) {
|
|
27
|
+
details.open = !details.open;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
activationHandler(event);
|
|
31
|
+
};
|
|
32
|
+
const classes = ['accordion-item', className].filter(Boolean).join(' ');
|
|
33
|
+
return (_jsxs("details", { ref: ref, id: id, className: classes, open: defaultOpen, ...props, children: [_jsxs("summary", { className: "accordion-item__summary", onKeyDown: handleSummaryKeyDown, children: [_jsx("span", { className: "accordion-item__title", children: title }), _jsx("svg", { className: "accordion-item__icon", width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: _jsx("path", { d: "M5 7.5L10 12.5L15 7.5", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })] }), _jsx("div", { className: "accordion-item__content", children: children })] }));
|
|
34
|
+
});
|
|
35
|
+
AccordionItem.displayName = 'AccordionItem';
|
|
36
|
+
/**
|
|
37
|
+
* Accessible Accordion container component
|
|
38
|
+
*
|
|
39
|
+
* WCAG Compliance:
|
|
40
|
+
* - 2.1.1 Keyboard: Full keyboard navigation support
|
|
41
|
+
* - 2.4.7 Focus Visible: Clear focus indicators on all interactive elements
|
|
42
|
+
* - 4.1.2 Name, Role, Value: Semantic HTML with proper structure
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```tsx
|
|
46
|
+
* <Accordion>
|
|
47
|
+
* <AccordionItem id="item-1" title="First Item">
|
|
48
|
+
* <p>Content 1</p>
|
|
49
|
+
* </AccordionItem>
|
|
50
|
+
* <AccordionItem id="item-2" title="Second Item">
|
|
51
|
+
* <p>Content 2</p>
|
|
52
|
+
* </AccordionItem>
|
|
53
|
+
* </Accordion>
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export const Accordion = React.forwardRef(({ children, allowMultiple = false, className = '', ...props }, ref) => {
|
|
57
|
+
const detailsRefs = React.useRef([]);
|
|
58
|
+
const handleToggle = (event) => {
|
|
59
|
+
if (!allowMultiple) {
|
|
60
|
+
const targetDetails = event.currentTarget;
|
|
61
|
+
// Only close others if the current item is being opened
|
|
62
|
+
if (targetDetails.open) {
|
|
63
|
+
// Close all other details elements
|
|
64
|
+
detailsRefs.current.forEach(details => {
|
|
65
|
+
if (details && details !== targetDetails && details.open) {
|
|
66
|
+
details.open = false;
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
const classes = ['accordion', className].filter(Boolean).join(' ');
|
|
73
|
+
// Clone children to add toggle handler and refs
|
|
74
|
+
const enhancedChildren = React.Children.map(children, (child, index) => {
|
|
75
|
+
if (React.isValidElement(child) && child.type === AccordionItem) {
|
|
76
|
+
return React.cloneElement(child, {
|
|
77
|
+
ref: (el) => {
|
|
78
|
+
detailsRefs.current[index] = el;
|
|
79
|
+
// Forward ref if child has one
|
|
80
|
+
if (typeof child.ref === 'function') {
|
|
81
|
+
child.ref(el);
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
onToggle: handleToggle,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return child;
|
|
88
|
+
});
|
|
89
|
+
return (_jsx("div", { ref: ref, className: classes, ...props, children: enhancedChildren }));
|
|
90
|
+
});
|
|
91
|
+
Accordion.displayName = 'Accordion';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Accordion/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AACtD,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Accordion, AccordionItem } from './Accordion';
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
/* Variants */
|
|
97
97
|
.btn--primary {
|
|
98
98
|
background-color: var(--color-primary-700, #0369a1);
|
|
99
|
-
color: var(--color-
|
|
99
|
+
color: var(--color-white, #ffffff);
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
.btn--primary:hover:not(:disabled) {
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
|
|
110
110
|
.btn--secondary {
|
|
111
111
|
background-color: var(--color-neutral-100, #f5f5f5);
|
|
112
|
-
color: var(--color-text-
|
|
112
|
+
color: var(--color-secondary-text-inverse, #525252);
|
|
113
113
|
border-color: var(--color-border-default, #bbbbbb);
|
|
114
114
|
}
|
|
115
115
|
|
|
@@ -128,6 +128,7 @@
|
|
|
128
128
|
|
|
129
129
|
.btn--ghost:hover:not(:disabled) {
|
|
130
130
|
background-color: var(--color-neutral-100, #f5f5f5);
|
|
131
|
+
color: var(--color-text-primary-gray, #171717);
|
|
131
132
|
}
|
|
132
133
|
|
|
133
134
|
.btn--ghost:active:not(:disabled) {
|
|
@@ -47,6 +47,10 @@ export interface DataTableProps<T> {
|
|
|
47
47
|
* Caption for the table (required for accessibility)
|
|
48
48
|
*/
|
|
49
49
|
caption?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Custom class name
|
|
52
|
+
*/
|
|
53
|
+
className?: string;
|
|
50
54
|
}
|
|
51
55
|
/**
|
|
52
56
|
* Accessible DataTable component
|
|
@@ -67,5 +71,5 @@ export interface DataTableProps<T> {
|
|
|
67
71
|
* />
|
|
68
72
|
* ```
|
|
69
73
|
*/
|
|
70
|
-
export declare function DataTable<T extends Record<string, any>>({ data, columns, getRowId, selectable, selectedRows, onSelectionChange, sortConfig, onSortChange, caption, }: DataTableProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
74
|
+
export declare function DataTable<T extends Record<string, any>>({ data, columns, getRowId, selectable, selectedRows, onSelectionChange, sortConfig, onSortChange, caption, className, }: DataTableProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
71
75
|
//# sourceMappingURL=DataTable.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataTable.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/DataTable.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAwC,MAAM,OAAO,CAAA;AAI5D,OAAO,iBAAiB,CAAA;AAExB,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAA;IACnD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B;;OAEG;IACH,IAAI,EAAE,CAAC,EAAE,CAAA;IAET;;OAEG;IACH,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAA;IAE7B;;OAEG;IACH,QAAQ,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,CAAA;IAE5B;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IAEpB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IAEvB;;OAEG;IACH,iBAAiB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;IAEnD;;OAEG;IACH,UAAU,CAAC,EAAE;QACX,MAAM,EAAE,MAAM,CAAA;QACd,SAAS,EAAE,KAAK,GAAG,MAAM,CAAA;KAC1B,CAAA;IAED;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,GAAG,MAAM,KAAK,IAAI,CAAA;IAElE;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"DataTable.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/DataTable.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAwC,MAAM,OAAO,CAAA;AAI5D,OAAO,iBAAiB,CAAA;AAExB,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAA;IACnD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B;;OAEG;IACH,IAAI,EAAE,CAAC,EAAE,CAAA;IAET;;OAEG;IACH,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAA;IAE7B;;OAEG;IACH,QAAQ,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,CAAA;IAE5B;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IAEpB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IAEvB;;OAEG;IACH,iBAAiB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;IAEnD;;OAEG;IACH,UAAU,CAAC,EAAE;QACX,MAAM,EAAE,MAAM,CAAA;QACd,SAAS,EAAE,KAAK,GAAG,MAAM,CAAA;KAC1B,CAAA;IAED;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,GAAG,MAAM,KAAK,IAAI,CAAA;IAElE;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EACvD,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,UAAkB,EAClB,YAAiB,EACjB,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,OAAO,EACP,SAAc,GACf,EAAE,cAAc,CAAC,CAAC,CAAC,2CAoMnB"}
|
|
@@ -24,7 +24,7 @@ import './DataTable.css';
|
|
|
24
24
|
* />
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
|
-
export function DataTable({ data, columns, getRowId, selectable = false, selectedRows = [], onSelectionChange, sortConfig, onSortChange, caption, }) {
|
|
27
|
+
export function DataTable({ data, columns, getRowId, selectable = false, selectedRows = [], onSelectionChange, sortConfig, onSortChange, caption, className = '', }) {
|
|
28
28
|
const [focusedRow, setFocusedRow] = useState(null);
|
|
29
29
|
const tableRef = useRef(null);
|
|
30
30
|
const rowRefs = useRef(new Map());
|
|
@@ -96,7 +96,7 @@ export function DataTable({ data, columns, getRowId, selectable = false, selecte
|
|
|
96
96
|
}, [data, selectable, handleSelectRow, getRowId]);
|
|
97
97
|
const allSelected = data.length > 0 && selectedRows.length === data.length;
|
|
98
98
|
const someSelected = selectedRows.length > 0 && selectedRows.length < data.length;
|
|
99
|
-
return (_jsx("div", { className:
|
|
99
|
+
return (_jsx("div", { className: ['data-table-wrapper', className].filter(Boolean).join(' '), children: _jsxs("table", { ref: tableRef, className: "data-table", "aria-label": caption, children: [caption && _jsx("caption", { className: "data-table-caption", children: caption }), _jsx("thead", { children: _jsxs("tr", { children: [selectable && (_jsx("th", { scope: "col", className: "data-table-header data-table-header--checkbox", children: _jsx(Checkbox, { checked: allSelected, "aria-label": "Select all rows", onChange: handleSelectAll, "aria-checked": allSelected ? 'true' : someSelected ? 'mixed' : 'false' }) })), columns.map((column) => (_jsx("th", { scope: "col", className: `data-table-header ${column.sortable ? 'data-table-header--sortable' : ''}`, style: column.width ? { width: column.width } : undefined, "aria-sort": sortConfig?.column === column.key
|
|
100
100
|
? sortConfig.direction === 'asc'
|
|
101
101
|
? 'ascending'
|
|
102
102
|
: 'descending'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* Link component styles */
|
|
2
2
|
.link {
|
|
3
|
-
color: var(--color-
|
|
3
|
+
color: var(--color-link, #0369a1);
|
|
4
4
|
text-decoration: underline;
|
|
5
5
|
text-underline-offset: 0.125em;
|
|
6
6
|
transition: color var(--motion-duration-normal, 200ms) var(--motion-easing-ease-out, cubic-bezier(0, 0, 0.2, 1));
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
|
|
27
27
|
/* Hover state */
|
|
28
28
|
.link:hover:not(:disabled) {
|
|
29
|
-
color: var(--color-
|
|
29
|
+
color: var(--color-link-hover, #075985);
|
|
30
30
|
text-decoration-thickness: 2px;
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../../src/components/Modal/Modal.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA4B,MAAM,OAAO,CAAA;AAGhD,OAAO,aAAa,CAAA;AAEpB,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,MAAM,EAAE,OAAO,CAAA;IAEf;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAA;IAEnB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAA;IAEb;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IAEzB;;OAEG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAE9B;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IAEvB;;OAEG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAA;IAElC;;OAEG;IACH,aAAa,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../../src/components/Modal/Modal.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA4B,MAAM,OAAO,CAAA;AAGhD,OAAO,aAAa,CAAA;AAEpB,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,MAAM,EAAE,OAAO,CAAA;IAEf;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAA;IAEnB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAA;IAEb;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IAEzB;;OAEG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAE9B;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IAEvB;;OAEG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAA;IAElC;;OAEG;IACH,aAAa,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;IAElC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CA4HtC,CAAA"}
|
|
@@ -30,7 +30,7 @@ import './Modal.css';
|
|
|
30
30
|
* </Modal>
|
|
31
31
|
* ```
|
|
32
32
|
*/
|
|
33
|
-
export const Modal = ({ isOpen, onClose, title, children, closeOnBackdropClick = true, closeOnEscape = true, size = 'md', returnFocusTo, }) => {
|
|
33
|
+
export const Modal = ({ isOpen, onClose, title, children, closeOnBackdropClick = true, closeOnEscape = true, size = 'md', returnFocusTo, className = '', }) => {
|
|
34
34
|
const dialogRef = useRef(null);
|
|
35
35
|
const contentRef = useRef(null);
|
|
36
36
|
const titleId = React.useId();
|
|
@@ -103,6 +103,6 @@ export const Modal = ({ isOpen, onClose, title, children, closeOnBackdropClick =
|
|
|
103
103
|
onClose();
|
|
104
104
|
}
|
|
105
105
|
};
|
|
106
|
-
return (_jsx("dialog", { ref: dialogRef, className: `modal modal--${size} ${isOpen ? 'modal--open' : ''}
|
|
106
|
+
return (_jsx("dialog", { ref: dialogRef, className: `modal modal--${size} ${isOpen ? 'modal--open' : ''} ${className}`.trim(), "aria-labelledby": titleId, "aria-describedby": descriptionId, onCancel: handleCancel, children: _jsxs("div", { ref: contentRef, className: "modal-content-wrapper", children: [_jsxs("div", { className: "modal-header", children: [_jsx("h2", { id: titleId, className: "modal-title", children: title }), _jsx(Button, { variant: "ghost", size: "sm", onClick: onClose, "aria-label": "Close modal", className: "modal-close", children: "\u00D7" })] }), _jsx("div", { id: descriptionId, className: "modal-content", children: children })] }) }));
|
|
107
107
|
};
|
|
108
108
|
Modal.displayName = 'Modal';
|
|
@@ -64,15 +64,15 @@
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
.tabs-tab--selected {
|
|
67
|
-
color: var(--color-
|
|
68
|
-
border-bottom-color: var(--color-
|
|
67
|
+
color: var(--color-link, #0369a1);
|
|
68
|
+
border-bottom-color: var(--color-link, #0369a1);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
.tabs--vertical .tabs-tab--selected {
|
|
72
72
|
border-bottom-color: transparent;
|
|
73
|
-
border-left-color: var(--color-
|
|
74
|
-
background-color: var(--color-
|
|
75
|
-
color: var(--color-
|
|
73
|
+
border-left-color: var(--color-link, #0369a1);
|
|
74
|
+
background-color: var(--color-background-secondary, #fafafa);
|
|
75
|
+
color: var(--color-link, #0369a1);
|
|
76
76
|
font-weight: var(--font-weight-semibold, 600);
|
|
77
77
|
}
|
|
78
78
|
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
.tabs--vertical .tabs-tab:hover:not(:disabled):not(.tabs-tab--selected) {
|
|
91
|
-
background-color: var(--color-
|
|
91
|
+
background-color: var(--color-background-secondary, #fafafa);
|
|
92
92
|
color: var(--color-text-primary, #171717);
|
|
93
93
|
}
|
|
94
94
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../src/components/Tabs/Tabs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAwC,MAAM,OAAO,CAAA;AAG5D,OAAO,YAAY,CAAA;AAEnB,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,KAAK,CAAC,SAAS,CAAA;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,KAAK,EAAE,OAAO,EAAE,CAAA;IAEhB;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAE1B;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;OAEG;IACH,iBAAiB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAExC;;OAEG;IACH,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAA;IAEvC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,WAAW,GAAG,QAAQ,CAAA;IAEvC;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../src/components/Tabs/Tabs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAwC,MAAM,OAAO,CAAA;AAG5D,OAAO,YAAY,CAAA;AAEnB,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,KAAK,CAAC,SAAS,CAAA;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,KAAK,EAAE,OAAO,EAAE,CAAA;IAEhB;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAE1B;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;OAEG;IACH,iBAAiB,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAExC;;OAEG;IACH,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAA;IAEvC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,WAAW,GAAG,QAAQ,CAAA;IAEvC;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAE1B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CA2KpC,CAAA"}
|
|
@@ -23,7 +23,7 @@ import './Tabs.css';
|
|
|
23
23
|
* />
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
|
-
export const Tabs = ({ items, defaultSelectedId, selectedId: controlledSelectedId, onSelectionChange, orientation = 'horizontal', activationMode = 'automatic', 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, }) => {
|
|
26
|
+
export const Tabs = ({ items, defaultSelectedId, selectedId: controlledSelectedId, onSelectionChange, orientation = 'horizontal', activationMode = 'automatic', 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, className = '', }) => {
|
|
27
27
|
const initialSelectedId = defaultSelectedId || items[0]?.id;
|
|
28
28
|
const [internalSelectedId, setInternalSelectedId] = useState(initialSelectedId);
|
|
29
29
|
const [focusedId, setFocusedId] = useState(initialSelectedId);
|
|
@@ -113,7 +113,7 @@ export const Tabs = ({ items, defaultSelectedId, selectedId: controlledSelectedI
|
|
|
113
113
|
}
|
|
114
114
|
}, [items, orientation, activationMode, handleSelect]);
|
|
115
115
|
const selectedTab = items.find((item) => item.id === selectedId);
|
|
116
|
-
return (_jsxs("div", { className:
|
|
116
|
+
return (_jsxs("div", { className: ['tabs', `tabs--${orientation}`, className].filter(Boolean).join(' '), children: [_jsx("div", { className: "tabs-list", role: "tablist", "aria-orientation": orientation, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, children: items.map((item, index) => {
|
|
117
117
|
const isSelected = item.id === selectedId;
|
|
118
118
|
const isFocused = item.id === effectiveFocusedId;
|
|
119
119
|
// In manual mode, focused tab should be focusable even if not selected
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toast.d.ts","sourceRoot":"","sources":["../../../src/components/Toast/Toast.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAA;AAIlD,OAAO,aAAa,CAAA;AAEpB,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,EAAE,EAAE,MAAM,CAAA;IAEV;;OAEG;IACH,OAAO,EAAE,MAAM,CAAA;IAEf;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAA;IAE/C;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IAErB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;OAEG;IACH,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAE/B;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"Toast.d.ts","sourceRoot":"","sources":["../../../src/components/Toast/Toast.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA8B,MAAM,OAAO,CAAA;AAIlD,OAAO,aAAa,CAAA;AAEpB,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,EAAE,EAAE,MAAM,CAAA;IAEV;;OAEG;IACH,OAAO,EAAE,MAAM,CAAA;IAEf;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAA;IAE/C;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IAErB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;OAEG;IACH,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAE/B;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IAEtB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CAuGtC,CAAA"}
|
|
@@ -30,7 +30,7 @@ import './Toast.css';
|
|
|
30
30
|
* />
|
|
31
31
|
* ```
|
|
32
32
|
*/
|
|
33
|
-
export const Toast = ({ id, message, type = 'info', dismissible = true, duration = 6000, onDismiss, pauseOnHover = true, }) => {
|
|
33
|
+
export const Toast = ({ id, message, type = 'info', dismissible = true, duration = 6000, onDismiss, pauseOnHover = true, className = '', }) => {
|
|
34
34
|
const [isPaused, setIsPaused] = useState(false);
|
|
35
35
|
const timeoutRef = React.useRef(null);
|
|
36
36
|
// Announce toast via ARIA live region
|
|
@@ -83,6 +83,7 @@ export const Toast = ({ id, message, type = 'info', dismissible = true, duration
|
|
|
83
83
|
const classes = [
|
|
84
84
|
'toast',
|
|
85
85
|
`toast--${type}`,
|
|
86
|
+
className,
|
|
86
87
|
]
|
|
87
88
|
.filter(Boolean)
|
|
88
89
|
.join(' ');
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,UAAU,CAAC;AAGzB,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,kCAAkC,CAAC;AACjD,cAAc,0BAA0B,CAAC;AACzC,cAAc,kCAAkC,CAAC;AACjD,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AAGxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,UAAU,CAAC;AAGzB,cAAc,kCAAkC,CAAC;AACjD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,kCAAkC,CAAC;AACjD,cAAc,0BAA0B,CAAC;AACzC,cAAc,kCAAkC,CAAC;AACjD,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AAGxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/styles/global.css
CHANGED
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
@import './components.css';
|
|
8
8
|
|
|
9
9
|
/* CSS Custom Properties from design tokens */
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
/* Light theme (default) */
|
|
11
|
+
:root,
|
|
12
|
+
[data-theme="light"] {
|
|
13
|
+
/* Colors - Base palette (same for both themes) */
|
|
12
14
|
--color-primary-50: #f0f9ff;
|
|
13
15
|
--color-primary-100: #e0f2fe;
|
|
14
16
|
--color-primary-200: #bae6fd;
|
|
@@ -45,18 +47,26 @@
|
|
|
45
47
|
|
|
46
48
|
--color-white: #ffffff;
|
|
47
49
|
--color-black: #000000;
|
|
50
|
+
--color-primary-gray: #171717;
|
|
48
51
|
|
|
52
|
+
/* Semantic colors - Light theme */
|
|
49
53
|
--color-background-default: #ffffff;
|
|
50
54
|
--color-background-secondary: #fafafa;
|
|
51
55
|
--color-background-tertiary: #f5f5f5;
|
|
56
|
+
--color-background-hover: #f5f5f5;
|
|
52
57
|
|
|
53
58
|
--color-text-primary: #171717;
|
|
54
59
|
--color-text-secondary: #525252;
|
|
55
60
|
--color-text-tertiary: #737373;
|
|
56
61
|
--color-text-inverse: #ffffff;
|
|
62
|
+
--color-secondary-text-inverse: #525252;
|
|
57
63
|
--color-text-disabled: #a3a3a3;
|
|
58
64
|
|
|
59
|
-
--color-
|
|
65
|
+
--color-link: #0369a1;
|
|
66
|
+
--color-link-hover: #075985;
|
|
67
|
+
|
|
68
|
+
--color-border-default: #e5e5e5;
|
|
69
|
+
--color-border-hover: #d4d4d4;
|
|
60
70
|
--color-border-focus: #0ea5e9;
|
|
61
71
|
--color-border-error: #ef4444;
|
|
62
72
|
|
|
@@ -114,6 +124,53 @@
|
|
|
114
124
|
--motion-easing-linear: linear;
|
|
115
125
|
}
|
|
116
126
|
|
|
127
|
+
/* Dark theme */
|
|
128
|
+
[data-theme="dark"] {
|
|
129
|
+
/* Semantic colors - Dark theme */
|
|
130
|
+
--color-background-default: #171717;
|
|
131
|
+
--color-background-secondary: #262626;
|
|
132
|
+
--color-background-tertiary: #404040;
|
|
133
|
+
--color-background-hover: #404040;
|
|
134
|
+
|
|
135
|
+
--color-text-primary: #fafafa;
|
|
136
|
+
--color-text-secondary: #d4d4d4;
|
|
137
|
+
--color-text-tertiary: #a3a3a3;
|
|
138
|
+
--color-text-inverse: #171717;
|
|
139
|
+
--color-text-disabled: #737373;
|
|
140
|
+
|
|
141
|
+
--color-link: #7dd3fc;
|
|
142
|
+
--color-link-hover: #38bdf8;
|
|
143
|
+
|
|
144
|
+
--color-border-default: #404040;
|
|
145
|
+
--color-border-hover: #525252;
|
|
146
|
+
--color-border-focus: #38bdf8;
|
|
147
|
+
--color-border-error: #ef4444;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/* Auto dark mode (respects system preference) */
|
|
151
|
+
@media (prefers-color-scheme: dark) {
|
|
152
|
+
:root:not([data-theme="light"]) {
|
|
153
|
+
--color-background-default: #171717;
|
|
154
|
+
--color-background-secondary: #262626;
|
|
155
|
+
--color-background-tertiary: #404040;
|
|
156
|
+
--color-background-hover: #404040;
|
|
157
|
+
|
|
158
|
+
--color-text-primary: #fafafa;
|
|
159
|
+
--color-text-secondary: #d4d4d4;
|
|
160
|
+
--color-text-tertiary: #a3a3a3;
|
|
161
|
+
--color-text-inverse: #171717;
|
|
162
|
+
--color-text-disabled: #737373;
|
|
163
|
+
|
|
164
|
+
--color-link: #7dd3fc;
|
|
165
|
+
--color-link-hover: #38bdf8;
|
|
166
|
+
|
|
167
|
+
--color-border-default: #404040;
|
|
168
|
+
--color-border-hover: #525252;
|
|
169
|
+
--color-border-focus: #38bdf8;
|
|
170
|
+
--color-border-error: #ef4444;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
117
174
|
/* CSS Reset */
|
|
118
175
|
*,
|
|
119
176
|
*::before,
|
|
@@ -140,6 +197,21 @@ body {
|
|
|
140
197
|
-moz-osx-font-smoothing: grayscale;
|
|
141
198
|
}
|
|
142
199
|
|
|
200
|
+
/* Ensure all text elements inherit theme colors */
|
|
201
|
+
p,
|
|
202
|
+
h1, h2, h3, h4, h5, h6,
|
|
203
|
+
span,
|
|
204
|
+
div,
|
|
205
|
+
article,
|
|
206
|
+
section,
|
|
207
|
+
aside,
|
|
208
|
+
main,
|
|
209
|
+
header,
|
|
210
|
+
footer,
|
|
211
|
+
nav {
|
|
212
|
+
color: inherit;
|
|
213
|
+
}
|
|
214
|
+
|
|
143
215
|
img,
|
|
144
216
|
picture,
|
|
145
217
|
video,
|