@tribepad/themis 1.9.4 → 1.10.0
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/CHANGELOG.md +15 -0
- package/dist/elements/AlertDialog/index.js +1 -1
- package/dist/elements/AlertDialog/index.js.map +1 -1
- package/dist/elements/AlertDialog/index.mjs +1 -1
- package/dist/elements/AlertDialog/index.mjs.map +1 -1
- package/dist/elements/Breadcrumbs/index.js +1 -1
- package/dist/elements/Breadcrumbs/index.js.map +1 -1
- package/dist/elements/Breadcrumbs/index.mjs +1 -1
- package/dist/elements/Breadcrumbs/index.mjs.map +1 -1
- package/dist/elements/Button/index.js +1 -1
- package/dist/elements/Button/index.js.map +1 -1
- package/dist/elements/Button/index.mjs +1 -1
- package/dist/elements/Button/index.mjs.map +1 -1
- package/dist/elements/Card/index.js +1 -1
- package/dist/elements/Card/index.js.map +1 -1
- package/dist/elements/Card/index.mjs +1 -1
- package/dist/elements/Card/index.mjs.map +1 -1
- package/dist/elements/Carousel/Carousel.d.ts +8 -1
- package/dist/elements/Carousel/Carousel.d.ts.map +1 -1
- package/dist/elements/Carousel/LazyCarousel.d.ts +1 -1
- package/dist/elements/Carousel/LazyCarousel.d.ts.map +1 -1
- package/dist/elements/Carousel/index.js +1 -1
- package/dist/elements/Carousel/index.js.map +1 -1
- package/dist/elements/Carousel/index.mjs +1 -1
- package/dist/elements/Carousel/index.mjs.map +1 -1
- package/dist/elements/ChatInterface/ChatLiveRegions.d.ts +2 -2
- package/dist/elements/ChatInterface/ChatLiveRegions.d.ts.map +1 -1
- package/dist/elements/ChatInterface/ChatMessageBubble.d.ts +1 -1
- package/dist/elements/ChatInterface/ChatMessageBubble.d.ts.map +1 -1
- package/dist/elements/ChatInterface/ChatThinkingDisplay.d.ts +2 -2
- package/dist/elements/ChatInterface/ChatThinkingDisplay.d.ts.map +1 -1
- package/dist/elements/ChatInterface/ChatTypingIndicator.d.ts +2 -2
- package/dist/elements/ChatInterface/ChatTypingIndicator.d.ts.map +1 -1
- package/dist/elements/ChatInterface/index.js +1 -1
- package/dist/elements/ChatInterface/index.js.map +1 -1
- package/dist/elements/ChatInterface/index.mjs +1 -1
- package/dist/elements/ChatInterface/index.mjs.map +1 -1
- package/dist/elements/FeatureIcon/FeatureIcon.d.ts +3 -0
- package/dist/elements/FeatureIcon/FeatureIcon.d.ts.map +1 -0
- package/dist/elements/FeatureIcon/FeatureIcon.styles.d.ts +17 -0
- package/dist/elements/FeatureIcon/FeatureIcon.styles.d.ts.map +1 -0
- package/dist/elements/FeatureIcon/FeatureIcon.types.d.ts +137 -0
- package/dist/elements/FeatureIcon/FeatureIcon.types.d.ts.map +1 -0
- package/dist/elements/FeatureIcon/index.d.ts +25 -0
- package/dist/elements/FeatureIcon/index.d.ts.map +1 -0
- package/dist/elements/FeatureIcon/index.js +3 -0
- package/dist/elements/FeatureIcon/index.js.map +1 -0
- package/dist/elements/FeatureIcon/index.mjs +3 -0
- package/dist/elements/FeatureIcon/index.mjs.map +1 -0
- package/dist/elements/FileField/index.js +1 -1
- package/dist/elements/FileField/index.js.map +1 -1
- package/dist/elements/FileField/index.mjs +1 -1
- package/dist/elements/FileField/index.mjs.map +1 -1
- package/dist/elements/Filters/index.js +1 -1
- package/dist/elements/Filters/index.js.map +1 -1
- package/dist/elements/Filters/index.mjs +1 -1
- package/dist/elements/Filters/index.mjs.map +1 -1
- package/dist/elements/Modal/Modal.styles.d.ts +2 -2
- package/dist/elements/Modal/Modal.types.d.ts +2 -2
- package/dist/elements/NumberField/index.js +1 -1
- package/dist/elements/NumberField/index.js.map +1 -1
- package/dist/elements/NumberField/index.mjs +1 -1
- package/dist/elements/NumberField/index.mjs.map +1 -1
- package/dist/elements/PageTitle/index.js +1 -1
- package/dist/elements/PageTitle/index.js.map +1 -1
- package/dist/elements/PageTitle/index.mjs +1 -1
- package/dist/elements/PageTitle/index.mjs.map +1 -1
- package/dist/elements/Pagination/index.js +1 -1
- package/dist/elements/Pagination/index.js.map +1 -1
- package/dist/elements/Pagination/index.mjs +1 -1
- package/dist/elements/Pagination/index.mjs.map +1 -1
- package/dist/elements/Panel/Panel.d.ts +1 -1
- package/dist/elements/Panel/Panel.types.d.ts +2 -2
- package/dist/elements/PasswordField/index.js +1 -1
- package/dist/elements/PasswordField/index.js.map +1 -1
- package/dist/elements/PasswordField/index.mjs +1 -1
- package/dist/elements/PasswordField/index.mjs.map +1 -1
- package/dist/elements/Resizable/index.js +1 -1
- package/dist/elements/Resizable/index.js.map +1 -1
- package/dist/elements/Resizable/index.mjs +1 -1
- package/dist/elements/Resizable/index.mjs.map +1 -1
- package/dist/elements/SearchField/index.js +1 -1
- package/dist/elements/SearchField/index.js.map +1 -1
- package/dist/elements/SearchField/index.mjs +1 -1
- package/dist/elements/SearchField/index.mjs.map +1 -1
- package/dist/elements/Select/Select.d.ts +3 -3
- package/dist/elements/Select/Select.d.ts.map +1 -1
- package/dist/elements/Sidebar/Sidebar.styles.d.ts +1 -1
- package/dist/elements/Sidebar/Sidebar.styles.d.ts.map +1 -1
- package/dist/elements/Sidebar/Sidebar.types.d.ts +2 -2
- package/dist/elements/Sidebar/SidebarRail.d.ts.map +1 -1
- package/dist/elements/Sidebar/index.js +1 -1
- package/dist/elements/Sidebar/index.js.map +1 -1
- package/dist/elements/Sidebar/index.mjs +1 -1
- package/dist/elements/Sidebar/index.mjs.map +1 -1
- package/dist/elements/Table/index.js +1 -1
- package/dist/elements/Table/index.js.map +1 -1
- package/dist/elements/Table/index.mjs +1 -1
- package/dist/elements/Table/index.mjs.map +1 -1
- package/dist/elements/TextField/index.js +1 -1
- package/dist/elements/TextField/index.js.map +1 -1
- package/dist/elements/TextField/index.mjs +1 -1
- package/dist/elements/TextField/index.mjs.map +1 -1
- package/dist/elements/Timeline/index.js +1 -1
- package/dist/elements/Timeline/index.js.map +1 -1
- package/dist/elements/Timeline/index.mjs +1 -1
- package/dist/elements/Timeline/index.mjs.map +1 -1
- package/dist/elements/Toast/index.js +1 -1
- package/dist/elements/Toast/index.js.map +1 -1
- package/dist/elements/Toast/index.mjs +1 -1
- package/dist/elements/Toast/index.mjs.map +1 -1
- package/dist/elements/Wizard/index.js +1 -1
- package/dist/elements/Wizard/index.js.map +1 -1
- package/dist/elements/Wizard/index.mjs +1 -1
- package/dist/elements/Wizard/index.mjs.map +1 -1
- package/dist/elements/index.d.ts +2 -0
- package/dist/elements/index.d.ts.map +1 -1
- package/dist/elements/index.js +1 -1
- package/dist/elements/index.js.map +1 -1
- package/dist/elements/index.mjs +1 -1
- package/dist/elements/index.mjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/dist/styles/animations.css +15 -0
- package/package.json +16 -14
- package/src/elements/FeatureIcon/FeatureIcon.stories.tsx +164 -0
|
@@ -312,3 +312,18 @@
|
|
|
312
312
|
animation: selection-pulse 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
313
313
|
}
|
|
314
314
|
|
|
315
|
+
/* =============================================================================
|
|
316
|
+
* Feature Icon Float
|
|
317
|
+
* Subtle, continuous vertical drift for FeatureIcon's `animated` variant.
|
|
318
|
+
* Pair with `motion-reduce:animate-none` to honour prefers-reduced-motion.
|
|
319
|
+
* ============================================================================= */
|
|
320
|
+
|
|
321
|
+
@keyframes feature-icon-float {
|
|
322
|
+
0%, 100% { transform: translateY(0); }
|
|
323
|
+
50% { transform: translateY(-2px); }
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
@utility feature-icon-animated {
|
|
327
|
+
animation: feature-icon-float 2.6s ease-in-out infinite;
|
|
328
|
+
}
|
|
329
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tribepad/themis",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "Accessible React component library built on React Aria primitives",
|
|
5
5
|
"author": "Tribepad <mbasford@tribepad.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -163,35 +163,35 @@
|
|
|
163
163
|
"@storybook/addon-a11y": "^10.4.4",
|
|
164
164
|
"@storybook/addon-mcp": "^0.6.0",
|
|
165
165
|
"@storybook/react-vite": "^10.4.4",
|
|
166
|
-
"@tailwindcss/vite": "^4.3.
|
|
166
|
+
"@tailwindcss/vite": "^4.3.2",
|
|
167
167
|
"@testing-library/jest-dom": "^6.9.1",
|
|
168
168
|
"@testing-library/react": "^16.3.2",
|
|
169
169
|
"@testing-library/user-event": "^14.6.1",
|
|
170
|
-
"@types/node": "^
|
|
170
|
+
"@types/node": "^26.1.0",
|
|
171
171
|
"@types/react": "^19.2.17",
|
|
172
172
|
"@types/react-dom": "^19.2.3",
|
|
173
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
174
|
-
"@typescript-eslint/parser": "^8.
|
|
173
|
+
"@typescript-eslint/eslint-plugin": "^8.62.1",
|
|
174
|
+
"@typescript-eslint/parser": "^8.62.1",
|
|
175
175
|
"@vitejs/plugin-react": "^6.0.2",
|
|
176
|
-
"@vitest/coverage-v8": "^4.1.
|
|
177
|
-
"eslint": "^10.
|
|
176
|
+
"@vitest/coverage-v8": "^4.1.10",
|
|
177
|
+
"eslint": "^10.6.0",
|
|
178
178
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
179
179
|
"eslint-plugin-storybook": "10.4.4",
|
|
180
180
|
"globals": "^17.6.0",
|
|
181
181
|
"happy-dom": "^20.10.2",
|
|
182
182
|
"jest-axe": "^10.0.0",
|
|
183
183
|
"jsdom": "^29.1.1",
|
|
184
|
-
"lucide-react": "^1.
|
|
185
|
-
"motion": "^12.
|
|
184
|
+
"lucide-react": "^1.23.0",
|
|
185
|
+
"motion": "^12.42.2",
|
|
186
186
|
"react": "^19.2.7",
|
|
187
187
|
"react-dom": "^19.2.7",
|
|
188
188
|
"size-limit": "^12.1.0",
|
|
189
189
|
"storybook": "^10.4.4",
|
|
190
190
|
"tsup": "^8.5.1",
|
|
191
|
-
"tsx": "^4.
|
|
192
|
-
"typescript": "^
|
|
193
|
-
"vite": "^8.
|
|
194
|
-
"vitest": "^4.1.
|
|
191
|
+
"tsx": "^4.23.0",
|
|
192
|
+
"typescript": "^6.0.3",
|
|
193
|
+
"vite": "^8.1.3",
|
|
194
|
+
"vitest": "^4.1.10",
|
|
195
195
|
"zod": "^4.4.3"
|
|
196
196
|
},
|
|
197
197
|
"pnpm": {
|
|
@@ -199,7 +199,9 @@
|
|
|
199
199
|
"esbuild"
|
|
200
200
|
],
|
|
201
201
|
"overrides": {
|
|
202
|
-
"postcss@<8.5.10": "^8.5.12"
|
|
202
|
+
"postcss@<8.5.10": "^8.5.12",
|
|
203
|
+
"undici@>=7.0.0 <7.28.0": "^7.28.0",
|
|
204
|
+
"@babel/core@<=7.29.0": "^7.29.6"
|
|
203
205
|
}
|
|
204
206
|
},
|
|
205
207
|
"engines": {
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FeatureIcon Component — Storybook Stories
|
|
3
|
+
*
|
|
4
|
+
* Display-only icon in a styled rounded container. These stories showcase the
|
|
5
|
+
* size, background, corner, icon-source, animation, and tooltip variations.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
9
|
+
import { expect, userEvent, within } from 'storybook/test';
|
|
10
|
+
import { FeatureIcon } from './FeatureIcon';
|
|
11
|
+
import type {
|
|
12
|
+
FeatureIconBackground,
|
|
13
|
+
FeatureIconCorners,
|
|
14
|
+
FeatureIconSection,
|
|
15
|
+
FeatureIconSize,
|
|
16
|
+
} from './FeatureIcon.types';
|
|
17
|
+
|
|
18
|
+
const SIZES: FeatureIconSize[] = ['sm', 'default', 'lg', 'xl'];
|
|
19
|
+
const BACKGROUNDS: FeatureIconBackground[] = [
|
|
20
|
+
'transparent',
|
|
21
|
+
'primary',
|
|
22
|
+
'pale',
|
|
23
|
+
'dark',
|
|
24
|
+
'status',
|
|
25
|
+
'sidekick',
|
|
26
|
+
];
|
|
27
|
+
const CORNERS: FeatureIconCorners[] = ['square', 'rounded', 'full'];
|
|
28
|
+
const SECTIONS: FeatureIconSection[] = [
|
|
29
|
+
'jobs',
|
|
30
|
+
'candidates',
|
|
31
|
+
'interviews',
|
|
32
|
+
'messages',
|
|
33
|
+
'reports',
|
|
34
|
+
'tasks',
|
|
35
|
+
'settings',
|
|
36
|
+
'notifications',
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
const meta = {
|
|
40
|
+
title: 'Elements/FeatureIcon',
|
|
41
|
+
component: FeatureIcon,
|
|
42
|
+
tags: ['autodocs'],
|
|
43
|
+
parameters: {
|
|
44
|
+
layout: 'centered',
|
|
45
|
+
docs: {
|
|
46
|
+
description: {
|
|
47
|
+
component:
|
|
48
|
+
'A display-only icon inside a styled, rounded container. Non-interactive by design — it represents a feature, product section, or status.\n\n**Key features:**\n- Sizes: sm, default, lg, xl\n- Backgrounds: transparent, primary, pale, dark, status, sidekick (AI gradient)\n- Corners: square, rounded, full\n- Icon: the design-specified default icon per section\n- Optional subtle animation on the icon (honours `prefers-reduced-motion`)\n- Optional tooltip — makes the icon keyboard-focusable and AT-named (WCAG 1.4.13 hoverable/dismissible)',
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
argTypes: {
|
|
53
|
+
size: { control: 'select', options: SIZES, description: 'Container / icon size' },
|
|
54
|
+
background: { control: 'select', options: BACKGROUNDS, description: 'Background treatment' },
|
|
55
|
+
corners: { control: 'select', options: CORNERS, description: 'Corner radius' },
|
|
56
|
+
tooltip: { control: 'text', description: 'Tooltip text (also names the icon for AT)' },
|
|
57
|
+
tooltipSide: {
|
|
58
|
+
control: 'select',
|
|
59
|
+
options: ['top', 'bottom', 'left', 'right'],
|
|
60
|
+
description: 'Tooltip placement',
|
|
61
|
+
},
|
|
62
|
+
// --- Icon ---
|
|
63
|
+
section: {
|
|
64
|
+
control: 'select',
|
|
65
|
+
options: SECTIONS,
|
|
66
|
+
description: 'Default icon, specified in the design (per section guidelines).',
|
|
67
|
+
table: { category: 'Icon' },
|
|
68
|
+
},
|
|
69
|
+
animated: {
|
|
70
|
+
control: 'boolean',
|
|
71
|
+
description: 'Subtle idle animation, applied to the icon.',
|
|
72
|
+
table: { category: 'Icon' },
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
args: {
|
|
76
|
+
size: 'default',
|
|
77
|
+
background: 'pale',
|
|
78
|
+
corners: 'rounded',
|
|
79
|
+
section: 'jobs',
|
|
80
|
+
animated: false,
|
|
81
|
+
},
|
|
82
|
+
} satisfies Meta<typeof FeatureIcon>;
|
|
83
|
+
|
|
84
|
+
export default meta;
|
|
85
|
+
type Story = StoryObj<typeof meta>;
|
|
86
|
+
|
|
87
|
+
/** Playground — drive every prop from the controls panel. */
|
|
88
|
+
export const Default: Story = {};
|
|
89
|
+
|
|
90
|
+
/** All sizes, side by side. */
|
|
91
|
+
export const Sizes: Story = {
|
|
92
|
+
render: () => (
|
|
93
|
+
<div className="flex items-end gap-6">
|
|
94
|
+
{SIZES.map((size) => (
|
|
95
|
+
<div key={size} className="flex flex-col items-center gap-2">
|
|
96
|
+
<FeatureIcon size={size} section="jobs" />
|
|
97
|
+
<span className="text-xs text-[var(--menu-muted)]">{size}</span>
|
|
98
|
+
</div>
|
|
99
|
+
))}
|
|
100
|
+
</div>
|
|
101
|
+
),
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/** Every background treatment. */
|
|
105
|
+
export const Backgrounds: Story = {
|
|
106
|
+
render: () => (
|
|
107
|
+
<div className="flex flex-wrap items-end gap-6">
|
|
108
|
+
{BACKGROUNDS.map((background) => (
|
|
109
|
+
<div key={background} className="flex flex-col items-center gap-2">
|
|
110
|
+
<FeatureIcon background={background} section="candidates" size="lg" />
|
|
111
|
+
<span className="text-xs text-[var(--menu-muted)]">{background}</span>
|
|
112
|
+
</div>
|
|
113
|
+
))}
|
|
114
|
+
</div>
|
|
115
|
+
),
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
/** Corner radius options. */
|
|
119
|
+
export const Corners: Story = {
|
|
120
|
+
render: () => (
|
|
121
|
+
<div className="flex items-end gap-6">
|
|
122
|
+
{CORNERS.map((corners) => (
|
|
123
|
+
<div key={corners} className="flex flex-col items-center gap-2">
|
|
124
|
+
<FeatureIcon corners={corners} section="interviews" size="lg" />
|
|
125
|
+
<span className="text-xs text-[var(--menu-muted)]">{corners}</span>
|
|
126
|
+
</div>
|
|
127
|
+
))}
|
|
128
|
+
</div>
|
|
129
|
+
),
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/** Subtle idle animation (disabled automatically under prefers-reduced-motion). */
|
|
133
|
+
export const Animated: Story = {
|
|
134
|
+
args: {
|
|
135
|
+
animated: true,
|
|
136
|
+
background: 'sidekick',
|
|
137
|
+
section: 'notifications',
|
|
138
|
+
size: 'xl',
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* With a tooltip the icon becomes keyboard-focusable and exposes role="img"
|
|
144
|
+
* with an accessible name. The play function focuses it and asserts the
|
|
145
|
+
* tooltip appears.
|
|
146
|
+
*/
|
|
147
|
+
export const WithTooltip: Story = {
|
|
148
|
+
args: {
|
|
149
|
+
tooltip: 'View interviews',
|
|
150
|
+
background: 'sidekick',
|
|
151
|
+
section: 'interviews',
|
|
152
|
+
size: 'lg',
|
|
153
|
+
},
|
|
154
|
+
play: async ({ canvas }) => {
|
|
155
|
+
const icon = canvas.getByRole('img', { name: 'View interviews' });
|
|
156
|
+
await userEvent.tab();
|
|
157
|
+
await expect(icon).toHaveFocus();
|
|
158
|
+
|
|
159
|
+
// Tooltip renders in a portal on document.body.
|
|
160
|
+
const body = within(document.body);
|
|
161
|
+
const tip = await body.findByRole('tooltip');
|
|
162
|
+
await expect(tip).toHaveTextContent('Ask Sidekick AI');
|
|
163
|
+
},
|
|
164
|
+
};
|