@helloimjolopez-pathway/pathway-components 0.7.2 → 0.8.1
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/components/_shared/focus-ring.js +45 -0
- package/components/module-icon/module-icon.jsx +11 -9
- package/components/nav-shell/nav-shell.jsx +6 -0
- package/components/sidenav/accounting-side-nav.jsx +3 -0
- package/components/sidenav/sidenav.jsx +7 -2
- package/components/top-nav/top-nav.jsx +16 -8
- package/dist/pathway-accounting-sidenav.js +6 -6
- package/dist/pathway-components.js +58 -58
- package/dist/pathway-sidenav.js +6 -6
- package/package.json +1 -1
- package/components/bottom-sheet/bottom-sheet-demo.jsx +0 -145
- package/components/nav-shell/nav-shell-demo.jsx +0 -59
- package/components/radio/radio-demo.jsx +0 -175
- package/components/scroll-to-enable/scroll-to-enable-demo.jsx +0 -125
- package/components/toggle-button/toggle-button-demo.jsx +0 -193
- package/components/tooltip/tooltip-demo.jsx +0 -149
- package/components/top-nav/top-nav-demo.jsx +0 -79
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Toggle Button's standalone demo. Imports the real module, so there is nothing
|
|
3
|
-
* here that can fall out of step with the shipped component: see
|
|
4
|
-
* components/_demo/harness.jsx for why the newer demos are generated.
|
|
5
|
-
*/
|
|
6
|
-
import React, { useState } from "react";
|
|
7
|
-
import { DemoChrome, mount } from "../_demo/harness.jsx";
|
|
8
|
-
import { ToggleButton, ToggleButtonOption, SIZES } from "./toggle-button.jsx";
|
|
9
|
-
import { Widget } from "../widget/widget.jsx";
|
|
10
|
-
import { TooltipProvider } from "../tooltip/tooltip.jsx";
|
|
11
|
-
|
|
12
|
-
const U = (n) => `var(--semantic-layout-units-${n})`;
|
|
13
|
-
const C = (n) => `var(--semantic-color-${n})`;
|
|
14
|
-
const Y = (n) => `var(--semantic-type-${n})`;
|
|
15
|
-
|
|
16
|
-
const STYLES = ["Primary", "Secondary", "Tertiary"];
|
|
17
|
-
const SIZE_KEYS = Object.keys(SIZES);
|
|
18
|
-
|
|
19
|
-
const VIEW = [
|
|
20
|
-
{ value: "bar", label: "Bar", icon: "bar_chart" },
|
|
21
|
-
{ value: "line", label: "Line", icon: "show_chart" },
|
|
22
|
-
{ value: "table", label: "Table", icon: "table_rows" },
|
|
23
|
-
];
|
|
24
|
-
const MONTHLY = "Budgets are set by month.";
|
|
25
|
-
const PERIOD = [
|
|
26
|
-
{ value: "d", label: "D", disabled: true, reason: `Daily totals aren't available. ${MONTHLY}` },
|
|
27
|
-
{ value: "w", label: "W", disabled: true, reason: `Weekly totals aren't available. ${MONTHLY}` },
|
|
28
|
-
{ value: "m", label: "M" },
|
|
29
|
-
{ value: "p", label: "P" },
|
|
30
|
-
{ value: "q", label: "Q" },
|
|
31
|
-
{ value: "y", label: "Y" },
|
|
32
|
-
];
|
|
33
|
-
const RANGE = [
|
|
34
|
-
{ value: "this", label: "This fiscal year" },
|
|
35
|
-
{ value: "last", label: "Last fiscal year" },
|
|
36
|
-
{ value: "ytd", label: "Year to date" },
|
|
37
|
-
{ value: "quarter", label: "This quarter" },
|
|
38
|
-
];
|
|
39
|
-
|
|
40
|
-
const card = {
|
|
41
|
-
background: C("fill-surface-elevated"), border: `1px solid ${C("stroke-static-neutral-base")}`,
|
|
42
|
-
borderRadius: U("cornerradius-large"), padding: U("padding-relaxed"),
|
|
43
|
-
display: "flex", flexDirection: "column", gap: U("gap-base"), minWidth: 0,
|
|
44
|
-
};
|
|
45
|
-
const h2 = { margin: 0, fontSize: Y("font-size-m"), lineHeight: Y("line-height-m-single"), fontWeight: Y("weight-semibold"), color: C("foreground-static-neutral-bold") };
|
|
46
|
-
const small = { fontSize: Y("font-size-xs"), lineHeight: Y("line-height-xs-single"), color: C("foreground-static-neutral-subtle") };
|
|
47
|
-
|
|
48
|
-
/* A chart placeholder: bars whose heights change with the view, so a choice is
|
|
49
|
-
visible straight away, which is the job the toggle does. */
|
|
50
|
-
function Chart({ view }) {
|
|
51
|
-
const data = [62, 44, 30, 28, 46, 80, 58, 64, 40, 54, 70, 70];
|
|
52
|
-
if (view === "table") {
|
|
53
|
-
return (
|
|
54
|
-
<div style={{ display: "grid", gridTemplateColumns: "1fr auto", gap: U("gap-xtight"), ...small }}>
|
|
55
|
-
{["Jan", "Feb", "Mar", "Apr", "May", "Jun"].map((m, i) => (
|
|
56
|
-
<React.Fragment key={m}><span>{m}</span><span style={{ color: C("foreground-static-neutral-base") }}>${(data[i] * 31).toLocaleString()}</span></React.Fragment>
|
|
57
|
-
))}
|
|
58
|
-
</div>
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
return (
|
|
62
|
-
<div style={{ display: "flex", alignItems: "flex-end", gap: U("gap-xtight"), height: 140 }}>
|
|
63
|
-
{data.map((v, i) => (
|
|
64
|
-
<div key={i} style={{ flex: 1, height: `${v}%`, background: C("fill-chart-sequential-07"),
|
|
65
|
-
borderRadius: view === "line" ? U("cornerradius-full") : U("cornerradius-small"),
|
|
66
|
-
maxHeight: view === "line" ? 6 : undefined, alignSelf: view === "line" ? "auto" : undefined,
|
|
67
|
-
marginBottom: view === "line" ? `${v - 6}%` : 0 }} />
|
|
68
|
-
))}
|
|
69
|
-
</div>
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function InWidget() {
|
|
74
|
-
const [view, setView] = useState("bar");
|
|
75
|
-
const [period, setPeriod] = useState("m");
|
|
76
|
-
const [bank, setBank] = useState("bar");
|
|
77
|
-
return (
|
|
78
|
-
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(min(100%, 360px), 1fr))", gap: U("gap-relaxed") }}>
|
|
79
|
-
<Widget title="Budget Compared to Actual" size="detail" inGrid={false}>
|
|
80
|
-
<div style={{ display: "flex", flexDirection: "column", gap: U("gap-base") }}>
|
|
81
|
-
<div style={{ display: "flex", justifyContent: "flex-end", minWidth: 0 }}>
|
|
82
|
-
<ToggleButton label="Chart view" options={VIEW} value={view} onChange={setView} showIcon />
|
|
83
|
-
</div>
|
|
84
|
-
<div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: U("gap-base"), minWidth: 0 }}>
|
|
85
|
-
<span style={{ fontSize: Y("font-size-xl"), lineHeight: Y("line-height-xl-single"), fontWeight: Y("weight-semibold"), color: C("foreground-static-neutral-strong") }}>2,000</span>
|
|
86
|
-
<ToggleButton label="Period" options={PERIOD} value={period} onChange={setPeriod} />
|
|
87
|
-
</div>
|
|
88
|
-
<Chart view={view} />
|
|
89
|
-
</div>
|
|
90
|
-
</Widget>
|
|
91
|
-
<Widget title="Bank Balances" size="detail" inGrid={false}>
|
|
92
|
-
<div style={{ display: "flex", flexDirection: "column", gap: U("gap-base") }}>
|
|
93
|
-
<div style={{ display: "flex", justifyContent: "flex-end" }}>
|
|
94
|
-
<ToggleButton label="Chart view" options={VIEW} value={bank} onChange={setBank} showIcon showLabel={false} />
|
|
95
|
-
</div>
|
|
96
|
-
<Chart view={bank} />
|
|
97
|
-
</div>
|
|
98
|
-
</Widget>
|
|
99
|
-
</div>
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function Styles() {
|
|
104
|
-
const [v, setV] = useState({});
|
|
105
|
-
return (
|
|
106
|
-
<section style={card}>
|
|
107
|
-
<h2 style={h2}>Styles and sizes</h2>
|
|
108
|
-
<p style={{ ...small, margin: 0 }}>Primary for one page-level toggle per view. Secondary inside cards, widgets, dialogs and sheets. Tertiary where Secondary fits but the selection should carry brand colour.</p>
|
|
109
|
-
{STYLES.map((st) => (
|
|
110
|
-
<div key={st} style={{ display: "flex", flexDirection: "column", gap: U("gap-xtight") }}>
|
|
111
|
-
<div style={small}>{st}</div>
|
|
112
|
-
<div style={{ display: "flex", alignItems: "center", gap: U("gap-relaxed"), flexWrap: "wrap" }}>
|
|
113
|
-
{SIZE_KEYS.map((sz) => (
|
|
114
|
-
<ToggleButton key={sz} label={`${st} ${sz}`} toggleStyle={st} size={sz} options={VIEW} showIcon
|
|
115
|
-
value={v[st + sz] ?? "bar"} onChange={(x) => setV((o) => ({ ...o, [st + sz]: x }))} />
|
|
116
|
-
))}
|
|
117
|
-
</div>
|
|
118
|
-
</div>
|
|
119
|
-
))}
|
|
120
|
-
<div style={small}>Icon only</div>
|
|
121
|
-
<div style={{ display: "flex", alignItems: "center", gap: U("gap-relaxed"), flexWrap: "wrap" }}>
|
|
122
|
-
{SIZE_KEYS.map((sz) => (
|
|
123
|
-
<ToggleButton key={sz} label={`Icon only ${sz}`} size={sz} options={VIEW} showIcon showLabel={false}
|
|
124
|
-
value={v["i" + sz] ?? "bar"} onChange={(x) => setV((o) => ({ ...o, ["i" + sz]: x }))} />
|
|
125
|
-
))}
|
|
126
|
-
</div>
|
|
127
|
-
</section>
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
function States() {
|
|
132
|
-
const [st, setSt] = useState("Secondary");
|
|
133
|
-
const states = [null, "hover", "focused", "pressed"];
|
|
134
|
-
const names = ["Rest", "Hover", "Focused", "Pressed"];
|
|
135
|
-
return (
|
|
136
|
-
<section style={card}>
|
|
137
|
-
<h2 style={h2}>States</h2>
|
|
138
|
-
<ToggleButton label="Style" options={STYLES.map((s) => ({ value: s, label: s }))} value={st} onChange={setSt} size="XS" />
|
|
139
|
-
<div style={{ display: "grid", gridTemplateColumns: "auto repeat(5, max-content)", gap: `${U("gap-base")} ${U("gap-relaxed")}`, alignItems: "center", overflowX: "auto" }}>
|
|
140
|
-
<span />{[...names, "Unavailable"].map((n) => <span key={n} style={small}>{n}</span>)}
|
|
141
|
-
{[false, true].map((sel) => (
|
|
142
|
-
<React.Fragment key={String(sel)}>
|
|
143
|
-
<span style={small}>{sel ? "Selected" : "Unselected"}</span>
|
|
144
|
-
{states.map((s, i) => (
|
|
145
|
-
<ToggleButtonOption key={i} toggleStyle={st} size="M" selected={sel} position="Only" label="Option" icon="bar_chart" forceState={s} tabIndex={-1} />
|
|
146
|
-
))}
|
|
147
|
-
{sel ? <span style={small}>never</span>
|
|
148
|
-
: <ToggleButtonOption toggleStyle={st} size="M" position="Only" label="Option" icon="bar_chart" disabled tabIndex={-1} />}
|
|
149
|
-
</React.Fragment>
|
|
150
|
-
))}
|
|
151
|
-
</div>
|
|
152
|
-
</section>
|
|
153
|
-
);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function Narrow() {
|
|
157
|
-
const [w, setW] = useState(520);
|
|
158
|
-
const [period, setPeriod] = useState("m");
|
|
159
|
-
const [range, setRange] = useState("this");
|
|
160
|
-
return (
|
|
161
|
-
<section style={card}>
|
|
162
|
-
<h2 style={h2}>Narrow space</h2>
|
|
163
|
-
<p style={{ ...small, margin: 0 }}>Drag the slider. Unavailable options move into More first, then options from the end. The selected option always stays in the row.</p>
|
|
164
|
-
<label style={{ ...small, display: "flex", alignItems: "center", gap: U("gap-tight") }}>
|
|
165
|
-
Container width {w}px
|
|
166
|
-
<input type="range" min={120} max={640} value={w} onChange={(e) => setW(+e.target.value)} style={{ flex: 1, maxWidth: 320 }} />
|
|
167
|
-
</label>
|
|
168
|
-
<div style={{ width: w, maxWidth: "100%", padding: U("padding-xtight"), border: `1px dashed ${C("stroke-static-neutral-bold")}`, borderRadius: U("cornerradius-base"), display: "flex", flexDirection: "column", gap: U("gap-base") }}>
|
|
169
|
-
<ToggleButton label="Period" options={PERIOD} value={period} onChange={setPeriod} />
|
|
170
|
-
<ToggleButton label="Range" options={RANGE} value={range} onChange={setRange} size="M" />
|
|
171
|
-
</div>
|
|
172
|
-
</section>
|
|
173
|
-
);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function App() {
|
|
177
|
-
return (
|
|
178
|
-
<DemoChrome title="Toggle Button"
|
|
179
|
-
blurb={"Pick one of two to five options; one is always selected. Keyboard: Tab to the group, arrows move and select, " +
|
|
180
|
-
"Home and End jump. Hover, focus or tap an unavailable option to see why."}>
|
|
181
|
-
<TooltipProvider>
|
|
182
|
-
<div style={{ display: "flex", flexDirection: "column", gap: U("gap-relaxed") }}>
|
|
183
|
-
<InWidget />
|
|
184
|
-
<Narrow />
|
|
185
|
-
<Styles />
|
|
186
|
-
<States />
|
|
187
|
-
</div>
|
|
188
|
-
</TooltipProvider>
|
|
189
|
-
</DemoChrome>
|
|
190
|
-
);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
mount(<App />);
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tooltip's standalone demo. Imports the real module, so there is nothing here
|
|
3
|
-
* that can fall out of step with the shipped component: see
|
|
4
|
-
* components/_demo/harness.jsx for why the newer demos are generated.
|
|
5
|
-
*/
|
|
6
|
-
import React, { useState } from "react";
|
|
7
|
-
import { DemoChrome, mount } from "../_demo/harness.jsx";
|
|
8
|
-
import { Tooltip, TooltipProvider } from "./tooltip.jsx";
|
|
9
|
-
import { Button } from "../button/button.jsx";
|
|
10
|
-
|
|
11
|
-
const U = (n) => `var(--semantic-layout-units-${n})`;
|
|
12
|
-
const C = (n) => `var(--semantic-color-${n})`;
|
|
13
|
-
const Y = (n) => `var(--semantic-type-${n})`;
|
|
14
|
-
|
|
15
|
-
const SIDES = ["top", "bottom", "left", "right"];
|
|
16
|
-
const ALIGNS = ["start", "center", "end"];
|
|
17
|
-
const LONG = "Weekly totals aren't available because budgets are set by month. Switch to Month to compare.";
|
|
18
|
-
|
|
19
|
-
const label = { fontSize: Y("font-size-xs"), lineHeight: Y("line-height-xs-single"), color: C("foreground-static-neutral-subtle") };
|
|
20
|
-
const card = {
|
|
21
|
-
background: C("fill-surface-elevated"), border: `1px solid ${C("stroke-static-neutral-base")}`,
|
|
22
|
-
borderRadius: U("cornerradius-large"), padding: U("padding-relaxed"),
|
|
23
|
-
display: "flex", flexDirection: "column", gap: U("gap-base"), minWidth: 0,
|
|
24
|
-
};
|
|
25
|
-
const h2 = { margin: 0, fontSize: Y("font-size-m"), lineHeight: Y("line-height-m-single"), fontWeight: Y("weight-semibold"), color: C("foreground-static-neutral-bold") };
|
|
26
|
-
|
|
27
|
-
/* An unavailable option stays focusable so it can say why, which a native
|
|
28
|
-
disabled button cannot. This stands in for a Toggle Button option. */
|
|
29
|
-
const Unavailable = React.forwardRef(function Unavailable({ children, ...rest }, ref) {
|
|
30
|
-
return (
|
|
31
|
-
<button ref={ref} type="button" aria-disabled="true" {...rest}
|
|
32
|
-
style={{ minWidth: U("accessibility-touch-target-aa-width"), minHeight: U("accessibility-touch-target-aa-height"),
|
|
33
|
-
padding: `0 ${U("padding-tight")}`, border: 0, borderRadius: U("cornerradius-base"), cursor: "not-allowed",
|
|
34
|
-
background: C("fill-action-disabled"), color: C("foreground-action-disabled"),
|
|
35
|
-
fontFamily: Y("family-brand"), fontSize: Y("font-size-s"), fontWeight: Y("weight-medium") }}>
|
|
36
|
-
{children}
|
|
37
|
-
</button>
|
|
38
|
-
);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
function Playground() {
|
|
42
|
-
const [side, setSide] = useState("top");
|
|
43
|
-
const [align, setAlign] = useState("center");
|
|
44
|
-
const [arrow, setArrow] = useState(true);
|
|
45
|
-
const [text, setText] = useState("Bar chart");
|
|
46
|
-
const pick = (list, v, set) => (
|
|
47
|
-
<div style={{ display: "flex", gap: U("gap-xtight"), flexWrap: "wrap" }}>
|
|
48
|
-
{list.map((x) => <Button key={x} size="S" buttonStyle={x === v ? "Fill" : "Outlined"} type="Secondary" text={x} onClick={() => set(x)} />)}
|
|
49
|
-
</div>
|
|
50
|
-
);
|
|
51
|
-
return (
|
|
52
|
-
<section style={card}>
|
|
53
|
-
<h2 style={h2}>Playground</h2>
|
|
54
|
-
<div style={{ display: "flex", gap: U("gap-relaxed"), flexWrap: "wrap" }}>
|
|
55
|
-
<div><div style={label}>Side</div>{pick(SIDES, side, setSide)}</div>
|
|
56
|
-
<div><div style={label}>Align</div>{pick(ALIGNS, align, setAlign)}</div>
|
|
57
|
-
<div><div style={label}>Arrow</div>{pick(["on", "off"], arrow ? "on" : "off", (x) => setArrow(x === "on"))}</div>
|
|
58
|
-
</div>
|
|
59
|
-
<label style={{ ...label, display: "flex", flexDirection: "column", gap: U("gap-xxtight"), maxWidth: 420 }}>
|
|
60
|
-
Content
|
|
61
|
-
<input id="tooltip-content" value={text} onChange={(e) => setText(e.target.value)}
|
|
62
|
-
style={{ font: "inherit", fontSize: Y("font-size-s"), padding: U("padding-xtight"), borderRadius: U("cornerradius-small"),
|
|
63
|
-
border: `1px solid ${C("stroke-static-neutral-bold")}`, background: C("fill-surface-elevated"), color: C("foreground-static-neutral-base") }} />
|
|
64
|
-
</label>
|
|
65
|
-
<div style={{ minHeight: 160, display: "flex", alignItems: "center", justifyContent: "center" }}>
|
|
66
|
-
<Tooltip content={text} side={side} align={align} arrow={arrow} open purpose="description">
|
|
67
|
-
<button type="button" style={{ width: 120, height: 44, border: `1px dashed ${C("stroke-static-neutral-bold")}`,
|
|
68
|
-
borderRadius: U("cornerradius-base"), background: "transparent", color: C("foreground-static-neutral-subtle"), font: "inherit" }}>
|
|
69
|
-
Trigger
|
|
70
|
-
</button>
|
|
71
|
-
</Tooltip>
|
|
72
|
-
</div>
|
|
73
|
-
</section>
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function Uses() {
|
|
78
|
-
return (
|
|
79
|
-
<section style={card}>
|
|
80
|
-
<h2 style={h2}>Try it: hover, Tab, tap, Esc</h2>
|
|
81
|
-
<div style={{ display: "flex", gap: U("gap-wide"), flexWrap: "wrap", alignItems: "flex-end" }}>
|
|
82
|
-
<div style={{ display: "flex", flexDirection: "column", gap: U("gap-tight") }}>
|
|
83
|
-
<span style={label}>Names icon-only controls</span>
|
|
84
|
-
<div style={{ display: "flex", gap: U("gap-xxtight") }}>
|
|
85
|
-
{[["bar_chart", "Bar chart"], ["show_chart", "Line chart"], ["table_rows", "Table"]].map(([icon, name]) => (
|
|
86
|
-
<Tooltip key={icon} content={name} purpose="label">
|
|
87
|
-
<Button buttonStyle="Naked" type="Secondary" size="M" showText={false} text={name}
|
|
88
|
-
leadingIcon={icon} showLeadingIcon />
|
|
89
|
-
</Tooltip>
|
|
90
|
-
))}
|
|
91
|
-
</div>
|
|
92
|
-
</div>
|
|
93
|
-
<div style={{ display: "flex", flexDirection: "column", gap: U("gap-tight") }}>
|
|
94
|
-
<span style={label}>Says why an option is unavailable</span>
|
|
95
|
-
<Tooltip content="Weekly totals aren't available. Budgets are set by month." persistOnPress>
|
|
96
|
-
<Unavailable>Week</Unavailable>
|
|
97
|
-
</Tooltip>
|
|
98
|
-
</div>
|
|
99
|
-
<div style={{ display: "flex", flexDirection: "column", gap: U("gap-tight") }}>
|
|
100
|
-
<span style={label}>Adds a short hint</span>
|
|
101
|
-
<Tooltip content="Includes payments that haven't cleared yet.">
|
|
102
|
-
<Button buttonStyle="Naked" type="Secondary" size="M" showText={false} text="About this balance"
|
|
103
|
-
leadingIcon="info" showLeadingIcon />
|
|
104
|
-
</Tooltip>
|
|
105
|
-
</div>
|
|
106
|
-
</div>
|
|
107
|
-
</section>
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function Grid() {
|
|
112
|
-
return (
|
|
113
|
-
<section style={card}>
|
|
114
|
-
<h2 style={h2}>Sides and alignment</h2>
|
|
115
|
-
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(220px, 1fr))", gap: U("gap-base") }}>
|
|
116
|
-
{SIDES.flatMap((s) => ALIGNS.map((a) => (
|
|
117
|
-
<div key={s + a} style={{ minHeight: 150, display: "flex", flexDirection: "column", gap: U("gap-tight"),
|
|
118
|
-
border: `1px dashed ${C("stroke-static-neutral-base")}`, borderRadius: U("cornerradius-base"), padding: U("padding-tight") }}>
|
|
119
|
-
<span style={label}>{s}, {a}</span>
|
|
120
|
-
<div style={{ flex: 1, display: "flex", alignItems: "center", justifyContent: "center" }}>
|
|
121
|
-
<Tooltip content={a === "center" ? "Bar chart" : LONG.slice(0, 44)} side={s} align={a} open>
|
|
122
|
-
<span tabIndex={-1} style={{ width: 28, height: 28, borderRadius: U("cornerradius-small"), background: C("fill-static-neutral-base") }} />
|
|
123
|
-
</Tooltip>
|
|
124
|
-
</div>
|
|
125
|
-
</div>
|
|
126
|
-
)))}
|
|
127
|
-
</div>
|
|
128
|
-
</section>
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function App() {
|
|
133
|
-
return (
|
|
134
|
-
<DemoChrome title="Tooltip"
|
|
135
|
-
blurb={"A short, plain-text label beside a control. It is always the opposite mode to the page: " +
|
|
136
|
-
"switch to Midnight to see it turn light. Hover waits 300ms, keyboard focus opens it at once, " +
|
|
137
|
-
"a tap shows it for 2.6 seconds, Esc closes it."}>
|
|
138
|
-
<TooltipProvider>
|
|
139
|
-
<div style={{ display: "flex", flexDirection: "column", gap: U("gap-relaxed") }}>
|
|
140
|
-
<Uses />
|
|
141
|
-
<Playground />
|
|
142
|
-
<Grid />
|
|
143
|
-
</div>
|
|
144
|
-
</TooltipProvider>
|
|
145
|
-
</DemoChrome>
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
mount(<App />);
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TopNav's standalone demo. Imports the real module, so there is nothing here
|
|
3
|
-
* that can fall out of step with the shipped component: see
|
|
4
|
-
* components/_demo/harness.jsx for why the newer demos are generated.
|
|
5
|
-
*
|
|
6
|
-
* Replaced the hand-written top-nav.html on 2026-10-30. That page carried its
|
|
7
|
-
* own copy of TopNav, and the copy had drifted from top-nav.jsx: it still
|
|
8
|
-
* abbreviated the mobile org label, still drew the campus line in Mono, and
|
|
9
|
-
* still sized the module mark at 24.
|
|
10
|
-
*/
|
|
11
|
-
import React, { useState } from "react";
|
|
12
|
-
import { DemoChrome, mount } from "../_demo/harness.jsx";
|
|
13
|
-
import { TopNav } from "./top-nav.jsx";
|
|
14
|
-
|
|
15
|
-
const U = (n) => `var(--semantic-layout-units-${n})`;
|
|
16
|
-
const C = (n) => `var(--semantic-color-${n})`;
|
|
17
|
-
const Y = (n) => `var(--semantic-type-${n})`;
|
|
18
|
-
|
|
19
|
-
const BARS = [
|
|
20
|
-
{ id: "desktop", label: "Desktop", width: 1200 },
|
|
21
|
-
{ id: "tablet", label: "Tablet", width: 768 },
|
|
22
|
-
{ id: "mobile", label: "Mobile", width: 393 },
|
|
23
|
-
];
|
|
24
|
-
const ORG = { id: "gcc", name: "Grace Community Church", shortName: "Grace Comm", campus: "Knoxville", initials: "GC" };
|
|
25
|
-
const USER = { name: "Jo Lopez", initials: "JL", email: "jo@gracecommunity.org" };
|
|
26
|
-
|
|
27
|
-
const label = { fontSize: Y("font-size-xs"), lineHeight: Y("line-height-xs-single"), color: C("foreground-static-neutral-subtle") };
|
|
28
|
-
const card = {
|
|
29
|
-
background: C("fill-surface-elevated"), border: `1px solid ${C("stroke-static-neutral-base")}`,
|
|
30
|
-
borderRadius: U("cornerradius-large"), padding: U("padding-relaxed"),
|
|
31
|
-
display: "flex", flexDirection: "column", gap: U("gap-base"), minWidth: 0,
|
|
32
|
-
};
|
|
33
|
-
const h2 = { margin: 0, fontSize: Y("font-size-m"), lineHeight: Y("line-height-m-single"), fontWeight: Y("weight-semibold"), color: C("foreground-static-neutral-bold") };
|
|
34
|
-
|
|
35
|
-
function App() {
|
|
36
|
-
const [showCampus, setShowCampus] = useState(false);
|
|
37
|
-
const [module, setModule] = useState("people");
|
|
38
|
-
const [brand, setBrand] = useState("amplify");
|
|
39
|
-
return (
|
|
40
|
-
<DemoChrome title="TopNav"
|
|
41
|
-
blurb={"The global bar across the top of every Pathway screen. Hover and open the module and org switchers. " +
|
|
42
|
-
"The campus line is off by default, as in Figma; turn it on below."}>
|
|
43
|
-
<div style={{ display: "flex", flexDirection: "column", gap: U("gap-relaxed") }}>
|
|
44
|
-
<section style={card}>
|
|
45
|
-
<h2 style={h2}>Options</h2>
|
|
46
|
-
<label style={{ ...label, display: "flex", alignItems: "center", gap: U("gap-xtight") }}>
|
|
47
|
-
<input id="topnav-show-campus" type="checkbox" checked={showCampus} onChange={(e) => setShowCampus(e.target.checked)} />
|
|
48
|
-
Show campus line (Figma "Show CityName")
|
|
49
|
-
</label>
|
|
50
|
-
<label style={{ ...label, display: "flex", alignItems: "center", gap: U("gap-xtight") }}>
|
|
51
|
-
Brand layout
|
|
52
|
-
<select id="topnav-brand" value={brand} onChange={(e) => setBrand(e.target.value)}>
|
|
53
|
-
<option value="amplify">Amplify</option>
|
|
54
|
-
<option value="newco">NewCo</option>
|
|
55
|
-
</select>
|
|
56
|
-
</label>
|
|
57
|
-
<label style={{ ...label, display: "flex", alignItems: "center", gap: U("gap-xtight") }}>
|
|
58
|
-
Module
|
|
59
|
-
<select id="topnav-module" value={module} onChange={(e) => setModule(e.target.value)}>
|
|
60
|
-
{["home", "people", "giving", "accounting", "communications"].map((m) => <option key={m} value={m}>{m}</option>)}
|
|
61
|
-
</select>
|
|
62
|
-
</label>
|
|
63
|
-
</section>
|
|
64
|
-
{BARS.map((b) => (
|
|
65
|
-
<section key={b.id} style={card}>
|
|
66
|
-
<h2 style={h2}>{b.label}</h2>
|
|
67
|
-
<div style={{ overflowX: "auto" }}>
|
|
68
|
-
<div style={{ width: b.width }}>
|
|
69
|
-
<TopNav key={module + brand} brand={brand} breakpoint={b.id} activeModuleId={module} org={ORG} user={USER} showCampus={showCampus} />
|
|
70
|
-
</div>
|
|
71
|
-
</div>
|
|
72
|
-
</section>
|
|
73
|
-
))}
|
|
74
|
-
</div>
|
|
75
|
-
</DemoChrome>
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
mount(<App />);
|