@empoweredvote/ev-ui 0.9.7 → 0.9.8
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/README.md +111 -111
- package/dist/index.js +28 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +28 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/tailwind-preset.js +81 -81
- package/src/tokens.js +415 -415
package/README.md
CHANGED
|
@@ -1,111 +1,111 @@
|
|
|
1
|
-
# @empoweredvote/ev-ui
|
|
2
|
-
|
|
3
|
-
Shared React component library for the [Empowered Vote](https://empowered.vote) civic engagement platform. Used across CompassV2, essentials, read-rank, civic-spaces, and other Empowered Vote apps.
|
|
4
|
-
|
|
5
|
-
[](https://www.npmjs.com/package/@empoweredvote/ev-ui)
|
|
6
|
-
|
|
7
|
-
## Installation
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm install @empoweredvote/ev-ui
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
The package is on public npm — no auth or `.npmrc` configuration required.
|
|
14
|
-
|
|
15
|
-
### Peer dependencies
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
npm install react react-dom @react-spring/web
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
Supported versions: React 17+, `@react-spring/web` 9+.
|
|
22
|
-
|
|
23
|
-
## Usage
|
|
24
|
-
|
|
25
|
-
```jsx
|
|
26
|
-
import { RadarChartCore, PoliticianCard, SiteHeader } from '@empoweredvote/ev-ui';
|
|
27
|
-
import { BallotIcon, CompassIcon } from '@empoweredvote/ev-ui';
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### Design tokens
|
|
31
|
-
|
|
32
|
-
Design tokens (colors, spacing, typography) are exported separately and can be used directly or via the Tailwind preset:
|
|
33
|
-
|
|
34
|
-
```js
|
|
35
|
-
// tailwind.config.js
|
|
36
|
-
import evPreset from '@empoweredvote/ev-ui/tailwind-preset';
|
|
37
|
-
|
|
38
|
-
export default {
|
|
39
|
-
presets: [evPreset],
|
|
40
|
-
// your config
|
|
41
|
-
};
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
Direct token import:
|
|
45
|
-
```js
|
|
46
|
-
import { colors, spacing } from '@empoweredvote/ev-ui/tokens';
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## Components
|
|
50
|
-
|
|
51
|
-
### Charts
|
|
52
|
-
- **`RadarChartCore`** — Interactive radar/spider chart with animated transitions, dual dataset overlays (e.g., your compass vs. a politician's), clickable spokes for inversion, and dynamic label wrapping.
|
|
53
|
-
|
|
54
|
-
### Politician Display
|
|
55
|
-
- **`PoliticianCard`** — Politician summary card with photo, title, district
|
|
56
|
-
- **`PoliticianProfile`** — Full profile page with contact, bio, legislative record
|
|
57
|
-
- **`CommitteeTable`** — Committee memberships and leadership roles
|
|
58
|
-
- **`LegislativeInlineSummary`**, **`LegislativeRecord`** — Bill/vote history
|
|
59
|
-
- **`JudicialScorecard`**, **`JudicialRecordDetail`** — Judicial record display
|
|
60
|
-
- **`SocialLinks`** — Social media icon links
|
|
61
|
-
- **`IssueTags`** — Topic/issue tag pills
|
|
62
|
-
- **`StanceAccordion`** — Collapsible stance list by topic
|
|
63
|
-
|
|
64
|
-
### Layout
|
|
65
|
-
- **`SiteHeader`** — Top nav bar with `defaultNavItems`, `defaultCtaButton` helpers
|
|
66
|
-
- **`Header`** — Simpler page header
|
|
67
|
-
- **`FilterSidebar`** — Filterable sidebar for results pages
|
|
68
|
-
- **`CategorySection`**, **`SubGroupSection`**, **`GovernmentBodySection`** — Grouped content sections
|
|
69
|
-
|
|
70
|
-
### Forms
|
|
71
|
-
- **`AuthForm`** — Login/signup form
|
|
72
|
-
|
|
73
|
-
### Icons
|
|
74
|
-
- **`BallotIcon`**, **`CompassIcon`**, **`BranchIcon`**
|
|
75
|
-
|
|
76
|
-
### Hooks
|
|
77
|
-
- **`useMediaQuery(query)`** — Responsive breakpoint hook
|
|
78
|
-
|
|
79
|
-
## Releasing
|
|
80
|
-
|
|
81
|
-
This package uses an **automated publish-and-fan-out pipeline**:
|
|
82
|
-
|
|
83
|
-
```bash
|
|
84
|
-
npm version patch # or minor / major
|
|
85
|
-
git push origin main --follow-tags
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
That's it. The tag push triggers `.github/workflows/publish.yml` which:
|
|
89
|
-
|
|
90
|
-
1. Publishes to npm using **OIDC trusted publishing** (no `NPM_TOKEN` — provenance attestations auto-generated)
|
|
91
|
-
2. Fires `repository_dispatch` to every consumer repo
|
|
92
|
-
3. Each consumer opens a PR bumping the dependency
|
|
93
|
-
4. Patch/minor bumps auto-merge after build-check passes
|
|
94
|
-
5. Render auto-deploys each consumer on merge
|
|
95
|
-
|
|
96
|
-
See [`README-AUTOBUMP.md`](./README-AUTOBUMP.md) for full pipeline details, how to add a new consumer, and debugging tips.
|
|
97
|
-
|
|
98
|
-
## Development
|
|
99
|
-
|
|
100
|
-
```bash
|
|
101
|
-
npm install
|
|
102
|
-
npm run build # tsup produces ESM + CJS bundles to dist/
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
## Design System Viewer
|
|
106
|
-
|
|
107
|
-
Design tokens are also rendered to a design system preview page deployed to GitHub Pages whenever `design-system/` or `src/tokens.js` changes on `main`. See `.github/workflows/deploy-design-system.yml`.
|
|
108
|
-
|
|
109
|
-
## License
|
|
110
|
-
|
|
111
|
-
Internal / Empowered Vote organization. See repository for details.
|
|
1
|
+
# @empoweredvote/ev-ui
|
|
2
|
+
|
|
3
|
+
Shared React component library for the [Empowered Vote](https://empowered.vote) civic engagement platform. Used across CompassV2, essentials, read-rank, civic-spaces, and other Empowered Vote apps.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@empoweredvote/ev-ui)
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @empoweredvote/ev-ui
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The package is on public npm — no auth or `.npmrc` configuration required.
|
|
14
|
+
|
|
15
|
+
### Peer dependencies
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install react react-dom @react-spring/web
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Supported versions: React 17+, `@react-spring/web` 9+.
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```jsx
|
|
26
|
+
import { RadarChartCore, PoliticianCard, SiteHeader } from '@empoweredvote/ev-ui';
|
|
27
|
+
import { BallotIcon, CompassIcon } from '@empoweredvote/ev-ui';
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Design tokens
|
|
31
|
+
|
|
32
|
+
Design tokens (colors, spacing, typography) are exported separately and can be used directly or via the Tailwind preset:
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
// tailwind.config.js
|
|
36
|
+
import evPreset from '@empoweredvote/ev-ui/tailwind-preset';
|
|
37
|
+
|
|
38
|
+
export default {
|
|
39
|
+
presets: [evPreset],
|
|
40
|
+
// your config
|
|
41
|
+
};
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Direct token import:
|
|
45
|
+
```js
|
|
46
|
+
import { colors, spacing } from '@empoweredvote/ev-ui/tokens';
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Components
|
|
50
|
+
|
|
51
|
+
### Charts
|
|
52
|
+
- **`RadarChartCore`** — Interactive radar/spider chart with animated transitions, dual dataset overlays (e.g., your compass vs. a politician's), clickable spokes for inversion, and dynamic label wrapping.
|
|
53
|
+
|
|
54
|
+
### Politician Display
|
|
55
|
+
- **`PoliticianCard`** — Politician summary card with photo, title, district
|
|
56
|
+
- **`PoliticianProfile`** — Full profile page with contact, bio, legislative record
|
|
57
|
+
- **`CommitteeTable`** — Committee memberships and leadership roles
|
|
58
|
+
- **`LegislativeInlineSummary`**, **`LegislativeRecord`** — Bill/vote history
|
|
59
|
+
- **`JudicialScorecard`**, **`JudicialRecordDetail`** — Judicial record display
|
|
60
|
+
- **`SocialLinks`** — Social media icon links
|
|
61
|
+
- **`IssueTags`** — Topic/issue tag pills
|
|
62
|
+
- **`StanceAccordion`** — Collapsible stance list by topic
|
|
63
|
+
|
|
64
|
+
### Layout
|
|
65
|
+
- **`SiteHeader`** — Top nav bar with `defaultNavItems`, `defaultCtaButton` helpers
|
|
66
|
+
- **`Header`** — Simpler page header
|
|
67
|
+
- **`FilterSidebar`** — Filterable sidebar for results pages
|
|
68
|
+
- **`CategorySection`**, **`SubGroupSection`**, **`GovernmentBodySection`** — Grouped content sections
|
|
69
|
+
|
|
70
|
+
### Forms
|
|
71
|
+
- **`AuthForm`** — Login/signup form
|
|
72
|
+
|
|
73
|
+
### Icons
|
|
74
|
+
- **`BallotIcon`**, **`CompassIcon`**, **`BranchIcon`**
|
|
75
|
+
|
|
76
|
+
### Hooks
|
|
77
|
+
- **`useMediaQuery(query)`** — Responsive breakpoint hook
|
|
78
|
+
|
|
79
|
+
## Releasing
|
|
80
|
+
|
|
81
|
+
This package uses an **automated publish-and-fan-out pipeline**:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npm version patch # or minor / major
|
|
85
|
+
git push origin main --follow-tags
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
That's it. The tag push triggers `.github/workflows/publish.yml` which:
|
|
89
|
+
|
|
90
|
+
1. Publishes to npm using **OIDC trusted publishing** (no `NPM_TOKEN` — provenance attestations auto-generated)
|
|
91
|
+
2. Fires `repository_dispatch` to every consumer repo
|
|
92
|
+
3. Each consumer opens a PR bumping the dependency
|
|
93
|
+
4. Patch/minor bumps auto-merge after build-check passes
|
|
94
|
+
5. Render auto-deploys each consumer on merge
|
|
95
|
+
|
|
96
|
+
See [`README-AUTOBUMP.md`](./README-AUTOBUMP.md) for full pipeline details, how to add a new consumer, and debugging tips.
|
|
97
|
+
|
|
98
|
+
## Development
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npm install
|
|
102
|
+
npm run build # tsup produces ESM + CJS bundles to dist/
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Design System Viewer
|
|
106
|
+
|
|
107
|
+
Design tokens are also rendered to a design system preview page deployed to GitHub Pages whenever `design-system/` or `src/tokens.js` changes on `main`. See `.github/workflows/deploy-design-system.yml`.
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
|
|
111
|
+
Internal / Empowered Vote organization. See repository for details.
|
package/dist/index.js
CHANGED
|
@@ -978,6 +978,9 @@ function Header({
|
|
|
978
978
|
logoSrc,
|
|
979
979
|
logoAlt = "Empowered Vote",
|
|
980
980
|
logoHref = "https://empowered.vote",
|
|
981
|
+
centerLogoSrc,
|
|
982
|
+
centerLogoHref,
|
|
983
|
+
centerLogoAlt,
|
|
981
984
|
navItems = [],
|
|
982
985
|
ctaButton,
|
|
983
986
|
secondaryAction,
|
|
@@ -1052,6 +1055,7 @@ function Header({
|
|
|
1052
1055
|
...style
|
|
1053
1056
|
},
|
|
1054
1057
|
container: {
|
|
1058
|
+
position: "relative",
|
|
1055
1059
|
maxWidth: "1512px",
|
|
1056
1060
|
margin: "0 auto",
|
|
1057
1061
|
padding: isMobile ? `${spacing[3]} ${spacing[3]}` : `${spacing[4]} ${spacing[6]}`,
|
|
@@ -1064,6 +1068,14 @@ function Header({
|
|
|
1064
1068
|
height: "43px",
|
|
1065
1069
|
cursor: "pointer"
|
|
1066
1070
|
},
|
|
1071
|
+
centerLogo: {
|
|
1072
|
+
position: "absolute",
|
|
1073
|
+
left: "50%",
|
|
1074
|
+
top: "50%",
|
|
1075
|
+
transform: "translate(-50%, -50%)",
|
|
1076
|
+
display: "flex",
|
|
1077
|
+
alignItems: "center"
|
|
1078
|
+
},
|
|
1067
1079
|
nav: {
|
|
1068
1080
|
display: isMobile ? "none" : "flex",
|
|
1069
1081
|
flex: "1 1 auto",
|
|
@@ -1312,14 +1324,18 @@ function Header({
|
|
|
1312
1324
|
))))
|
|
1313
1325
|
);
|
|
1314
1326
|
};
|
|
1327
|
+
const featureOnLeft = isMobile && centerLogoSrc;
|
|
1328
|
+
const leftLogoSrc = featureOnLeft ? centerLogoSrc : logoSrc;
|
|
1329
|
+
const leftLogoAlt = featureOnLeft ? centerLogoAlt || logoAlt : logoAlt;
|
|
1330
|
+
const leftLogoHref = featureOnLeft ? centerLogoHref || logoHref : logoHref;
|
|
1315
1331
|
return /* @__PURE__ */ import_react6.default.createElement("header", { style: styles2.header }, /* @__PURE__ */ import_react6.default.createElement("div", { style: styles2.container }, /* @__PURE__ */ import_react6.default.createElement(
|
|
1316
1332
|
"a",
|
|
1317
1333
|
{
|
|
1318
|
-
href:
|
|
1319
|
-
onClick: (e) => handleNavClick(e,
|
|
1334
|
+
href: leftLogoHref,
|
|
1335
|
+
onClick: (e) => handleNavClick(e, leftLogoHref),
|
|
1320
1336
|
style: { display: "flex", alignItems: "center", flexShrink: 0 }
|
|
1321
1337
|
},
|
|
1322
|
-
|
|
1338
|
+
leftLogoSrc ? /* @__PURE__ */ import_react6.default.createElement("img", { src: leftLogoSrc, alt: leftLogoAlt, style: styles2.logo }) : /* @__PURE__ */ import_react6.default.createElement(
|
|
1323
1339
|
"span",
|
|
1324
1340
|
{
|
|
1325
1341
|
style: {
|
|
@@ -1331,6 +1347,15 @@ function Header({
|
|
|
1331
1347
|
},
|
|
1332
1348
|
"empowered.vote"
|
|
1333
1349
|
)
|
|
1350
|
+
), centerLogoSrc && !isMobile && /* @__PURE__ */ import_react6.default.createElement(
|
|
1351
|
+
"a",
|
|
1352
|
+
{
|
|
1353
|
+
href: centerLogoHref || logoHref,
|
|
1354
|
+
onClick: (e) => handleNavClick(e, centerLogoHref || logoHref),
|
|
1355
|
+
style: styles2.centerLogo,
|
|
1356
|
+
"aria-label": centerLogoAlt || "Feature home"
|
|
1357
|
+
},
|
|
1358
|
+
/* @__PURE__ */ import_react6.default.createElement("img", { src: centerLogoSrc, alt: centerLogoAlt || "", style: styles2.logo })
|
|
1334
1359
|
), /* @__PURE__ */ import_react6.default.createElement("nav", { style: styles2.nav, className: "ev-header-nav" }, navItems.map((item, idx) => /* @__PURE__ */ import_react6.default.createElement(NavLink, { key: idx, item }))), /* @__PURE__ */ import_react6.default.createElement("div", { style: { display: isMobile ? "none" : "flex", alignItems: "center", gap: spacing[3], flexShrink: 0 } }, secondaryAction && import_react6.default.isValidElement(secondaryAction) && secondaryAction, secondaryAction && !import_react6.default.isValidElement(secondaryAction) && /* @__PURE__ */ import_react6.default.createElement(
|
|
1335
1360
|
"a",
|
|
1336
1361
|
{
|