@jsenv/navi 0.4.2 → 0.5.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.
@@ -21196,11 +21196,15 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
21196
21196
  @layer navi {
21197
21197
  .navi_button {
21198
21198
  position: relative;
21199
- display: inline-block;
21199
+ display: inline-flex;
21200
+ width: fit-content;
21201
+ height: fit-content;
21200
21202
  padding: 0;
21201
21203
  background: none;
21202
21204
  border: none;
21205
+ border-radius: inherit;
21203
21206
  outline: none;
21207
+ cursor: pointer;
21204
21208
 
21205
21209
  --border-width: 1px;
21206
21210
  --outline-width: 1px;
@@ -21294,6 +21298,9 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
21294
21298
  --color: var(--color-readonly);
21295
21299
  }
21296
21300
  /* Disabled */
21301
+ .navi_button[data-disabled] {
21302
+ cursor: default;
21303
+ }
21297
21304
  .navi_button[data-disabled] .navi_button_content {
21298
21305
  --border-color: var(--border-color-disabled);
21299
21306
  --background-color: var(--background-color-disabled);
@@ -21355,6 +21362,8 @@ const ButtonBasic = forwardRef((props, ref) => {
21355
21362
  constraints = [],
21356
21363
  autoFocus,
21357
21364
  appearance = "navi",
21365
+ alignX = "start",
21366
+ style,
21358
21367
  discrete,
21359
21368
  children,
21360
21369
  ...rest
@@ -21375,10 +21384,18 @@ const ButtonBasic = forwardRef((props, ref) => {
21375
21384
  } else {
21376
21385
  buttonChildren = children;
21377
21386
  }
21387
+ const innerStyle = {
21388
+ ...style
21389
+ };
21390
+ if (alignX !== "start") {
21391
+ innerStyle["align-self"] = alignX === "center" ? "center" : "flex-end";
21392
+ }
21378
21393
  return jsx("button", {
21379
21394
  ...rest,
21380
21395
  ref: innerRef,
21381
21396
  className: appearance === "navi" ? "navi_button" : undefined,
21397
+ style: innerStyle,
21398
+ disabled: innerDisabled,
21382
21399
  "data-discrete": discrete ? "" : undefined,
21383
21400
  "data-readonly": innerReadOnly ? "" : undefined,
21384
21401
  "data-readonly-silent": innerLoading ? "" : undefined,
@@ -27636,12 +27653,14 @@ const useSignalSync = (value, initialValue = value) => {
27636
27653
  const FontSizedSvg = ({
27637
27654
  width = "1em",
27638
27655
  height = "1em",
27656
+ style,
27639
27657
  children,
27640
27658
  ...props
27641
27659
  }) => {
27642
27660
  return jsx("span", {
27643
27661
  ...props,
27644
27662
  style: {
27663
+ ...style,
27645
27664
  display: "flex",
27646
27665
  alignItems: "center",
27647
27666
  width,
@@ -27803,6 +27822,63 @@ const Overflow = ({
27803
27822
  });
27804
27823
  };
27805
27824
 
27825
+ installImportMetaCss(import.meta);import.meta.css = /* css */`
27826
+ :root {
27827
+ --navi-icon-align-y: center;
27828
+ }
27829
+
27830
+ .navi_text {
27831
+ display: inline-flex;
27832
+ align-items: baseline;
27833
+ gap: 0.1em;
27834
+ }
27835
+
27836
+ .navi_icon {
27837
+ --align-y: var(--navi-icon-align-y, center);
27838
+
27839
+ display: inline-flex;
27840
+ width: 1em;
27841
+ height: 1em;
27842
+ flex-shrink: 0;
27843
+ align-self: var(--align-y);
27844
+ line-height: 1em;
27845
+ }
27846
+ `;
27847
+ const Text = ({
27848
+ children,
27849
+ ...rest
27850
+ }) => {
27851
+ return jsx("span", {
27852
+ ...rest,
27853
+ className: "navi_text",
27854
+ children: children
27855
+ });
27856
+ };
27857
+ const alignYMapping = {
27858
+ start: "flex-start",
27859
+ center: "center",
27860
+ end: "flex-end"
27861
+ };
27862
+ const Icon = ({
27863
+ alignY,
27864
+ style,
27865
+ children,
27866
+ ...rest
27867
+ }) => {
27868
+ const innerStyle = {
27869
+ ...style
27870
+ };
27871
+ if (alignY !== "center") {
27872
+ innerStyle["--align-y"] = alignYMapping[alignY];
27873
+ }
27874
+ return jsx("span", {
27875
+ ...rest,
27876
+ className: "navi_icon",
27877
+ style: innerStyle,
27878
+ children: children
27879
+ });
27880
+ };
27881
+
27806
27882
  installImportMetaCss(import.meta);import.meta.css = /* css */`
27807
27883
  .text_and_count {
27808
27884
  display: flex;
@@ -27912,4 +27988,4 @@ const useDependenciesDiff = (inputs) => {
27912
27988
  return diffRef.current;
27913
27989
  };
27914
27990
 
27915
- export { ActionRenderer, ActiveKeyboardShortcuts, Button, Checkbox, CheckboxList, Col, Colgroup, Details, Editable, ErrorBoundaryContext, FontSizedSvg, Form, IconAndText, Input, Label, Link, LinkWithIcon, Overflow, Radio, RadioList, Route, RowNumberCol, RowNumberTableCell, SINGLE_SPACE_CONSTRAINT, SVGMaskOverlay, Select, SelectionContext, SummaryMarker, Tab, TabList, Table, TableCell, Tbody, TextAndCount, Thead, Tr, UITransition, actionIntegratedVia, addCustomMessage, createAction, createSelectionKeyboardShortcuts, createUniqueValueConstraint, defineRoutes, enableDebugActions, enableDebugOnDocumentLoading, goBack, goForward, goTo, isCellSelected, isColumnSelected, isRowSelected, openCallout, rawUrlPart, reload, removeCustomMessage, rerunActions, resource, setBaseUrl, stopLoad, stringifyTableSelectionValue, updateActions, useActionData, useActionStatus, useCellsAndColumns, useDependenciesDiff, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useKeyboardShortcuts, useNavState, useRouteStatus, useRunOnMount, useSelectableElement, useSelectionController, useSignalSync, useStateArray, valueInLocalStorage };
27991
+ export { ActionRenderer, ActiveKeyboardShortcuts, Button, Checkbox, CheckboxList, Col, Colgroup, Details, Editable, ErrorBoundaryContext, FontSizedSvg, Form, Icon, IconAndText, Input, Label, Link, LinkWithIcon, Overflow, Radio, RadioList, Route, RowNumberCol, RowNumberTableCell, SINGLE_SPACE_CONSTRAINT, SVGMaskOverlay, Select, SelectionContext, SummaryMarker, Tab, TabList, Table, TableCell, Tbody, Text, TextAndCount, Thead, Tr, UITransition, actionIntegratedVia, addCustomMessage, createAction, createSelectionKeyboardShortcuts, createUniqueValueConstraint, defineRoutes, enableDebugActions, enableDebugOnDocumentLoading, goBack, goForward, goTo, isCellSelected, isColumnSelected, isRowSelected, openCallout, rawUrlPart, reload, removeCustomMessage, rerunActions, resource, setBaseUrl, stopLoad, stringifyTableSelectionValue, updateActions, useActionData, useActionStatus, useCellsAndColumns, useDependenciesDiff, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useKeyboardShortcuts, useNavState, useRouteStatus, useRunOnMount, useSelectableElement, useSelectionController, useSignalSync, useStateArray, valueInLocalStorage };
package/index.js CHANGED
@@ -88,6 +88,7 @@ export { FontSizedSvg } from "./src/components/svg/font_sized_svg.jsx";
88
88
  export { IconAndText } from "./src/components/svg/icon_and_text.jsx";
89
89
  export { SVGMaskOverlay } from "./src/components/svg/svg_mask_overlay.jsx";
90
90
  export { Overflow } from "./src/components/text/overflow.jsx";
91
+ export { Icon, Text } from "./src/components/text/text.jsx";
91
92
  export { TextAndCount } from "./src/components/text/text_and_count.jsx";
92
93
  // Callout, dialogs, ...
93
94
  export { openCallout } from "./src/components/callout/callout.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/navi",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "description": "Library of components including navigation to create frontend applications",
5
5
  "repository": {
6
6
  "type": "git",
@@ -40,11 +40,15 @@ import.meta.css = /* css */ `
40
40
  @layer navi {
41
41
  .navi_button {
42
42
  position: relative;
43
- display: inline-block;
43
+ display: inline-flex;
44
+ width: fit-content;
45
+ height: fit-content;
44
46
  padding: 0;
45
47
  background: none;
46
48
  border: none;
49
+ border-radius: inherit;
47
50
  outline: none;
51
+ cursor: pointer;
48
52
 
49
53
  --border-width: 1px;
50
54
  --outline-width: 1px;
@@ -138,6 +142,9 @@ import.meta.css = /* css */ `
138
142
  --color: var(--color-readonly);
139
143
  }
140
144
  /* Disabled */
145
+ .navi_button[data-disabled] {
146
+ cursor: default;
147
+ }
141
148
  .navi_button[data-disabled] .navi_button_content {
142
149
  --border-color: var(--border-color-disabled);
143
150
  --background-color: var(--background-color-disabled);
@@ -200,6 +207,8 @@ const ButtonBasic = forwardRef((props, ref) => {
200
207
  constraints = [],
201
208
  autoFocus,
202
209
  appearance = "navi",
210
+ alignX = "start",
211
+ style,
203
212
  discrete,
204
213
  children,
205
214
  ...rest
@@ -221,11 +230,18 @@ const ButtonBasic = forwardRef((props, ref) => {
221
230
  buttonChildren = children;
222
231
  }
223
232
 
233
+ const innerStyle = { ...style };
234
+ if (alignX !== "start") {
235
+ innerStyle["align-self"] = alignX === "center" ? "center" : "flex-end";
236
+ }
237
+
224
238
  return (
225
239
  <button
226
240
  {...rest}
227
241
  ref={innerRef}
228
242
  className={appearance === "navi" ? "navi_button" : undefined}
243
+ style={innerStyle}
244
+ disabled={innerDisabled}
229
245
  data-discrete={discrete ? "" : undefined}
230
246
  data-readonly={innerReadOnly ? "" : undefined}
231
247
  data-readonly-silent={innerLoading ? "" : undefined}
@@ -23,6 +23,7 @@
23
23
  export const FontSizedSvg = ({
24
24
  width = "1em",
25
25
  height = "1em",
26
+ style,
26
27
  children,
27
28
  ...props
28
29
  }) => {
@@ -30,6 +31,7 @@ export const FontSizedSvg = ({
30
31
  <span
31
32
  {...props}
32
33
  style={{
34
+ ...style,
33
35
  display: "flex",
34
36
  alignItems: "center",
35
37
  width,
@@ -0,0 +1,465 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>Text and Icon Demo</title>
6
+ <script type="importmap">
7
+ {
8
+ "imports": {
9
+ "preact": "https://esm.sh/preact@10.22.0",
10
+ "preact/": "https://esm.sh/preact@10.22.0/"
11
+ }
12
+ }
13
+ </script>
14
+ </head>
15
+ <body>
16
+ <div id="app"></div>
17
+ <script type="module" jsenv-type="module/jsx">
18
+ import { render } from "preact";
19
+ /* eslint-disable no-unused-vars */
20
+ import { Text, Icon } from "../text.jsx";
21
+
22
+ // Sample SVG icons
23
+ const HomeIcon = () => (
24
+ <svg
25
+ viewBox="0 0 24 24"
26
+ width="100%"
27
+ height="100%"
28
+ xmlns="http://www.w3.org/2000/svg"
29
+ >
30
+ <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" fill="currentColor" />
31
+ </svg>
32
+ );
33
+
34
+ const UserIcon = () => (
35
+ <svg
36
+ viewBox="0 0 24 24"
37
+ width="100%"
38
+ height="100%"
39
+ xmlns="http://www.w3.org/2000/svg"
40
+ >
41
+ <path
42
+ d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"
43
+ fill="currentColor"
44
+ />
45
+ </svg>
46
+ );
47
+
48
+ const SettingsIcon = () => (
49
+ <svg
50
+ viewBox="0 0 24 24"
51
+ width="100%"
52
+ height="100%"
53
+ xmlns="http://www.w3.org/2000/svg"
54
+ >
55
+ <path
56
+ d="M19.14,12.94c0.04-0.3,0.06-0.61,0.06-0.94c0-0.32-0.02-0.64-0.07-0.94l2.03-1.58c0.18-0.14,0.23-0.41,0.12-0.61 l-1.92-3.32c-0.12-0.22-0.37-0.29-0.59-0.22l-2.39,0.96c-0.5-0.38-1.03-0.7-1.62-0.94L14.4,2.81c-0.04-0.24-0.24-0.41-0.48-0.41 h-3.84c-0.24,0-0.43,0.17-0.47,0.41L9.25,5.35C8.66,5.59,8.12,5.92,7.63,6.29L5.24,5.33c-0.22-0.08-0.47,0-0.59,0.22L2.74,8.87 C2.62,9.08,2.66,9.34,2.86,9.48l2.03,1.58C4.84,11.36,4.82,11.69,4.82,12s0.02,0.64,0.07,0.94l-2.03,1.58 c-0.18,0.14-0.23,0.41-0.12,0.61l1.92,3.32c0.12,0.22,0.37,0.29,0.59,0.22l2.39-0.96c0.5,0.38,1.03,0.7,1.62,0.94l0.36,2.54 c0.05,0.24,0.24,0.41,0.48,0.41h3.84c0.24,0,0.44-0.17,0.47-0.41l0.36-2.54c0.59-0.24,1.13-0.56,1.62-0.94l2.39,0.96 c0.22,0.08,0.47,0,0.59-0.22l1.92-3.32c0.12-0.22,0.07-0.47-0.12-0.61L19.14,12.94z M12,15.6c-1.98,0-3.6-1.62-3.6-3.6 s1.62-3.6,3.6-3.6s3.6,1.62,3.6,3.6S13.98,15.6,12,15.6z"
57
+ fill="currentColor"
58
+ />
59
+ </svg>
60
+ );
61
+
62
+ const SearchIcon = () => (
63
+ <svg
64
+ viewBox="0 0 24 24"
65
+ width="100%"
66
+ height="100%"
67
+ xmlns="http://www.w3.org/2000/svg"
68
+ >
69
+ <path
70
+ d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"
71
+ fill="currentColor"
72
+ />
73
+ </svg>
74
+ );
75
+
76
+ const StarIcon = () => (
77
+ <svg
78
+ viewBox="0 0 24 24"
79
+ width="100%"
80
+ height="100%"
81
+ xmlns="http://www.w3.org/2000/svg"
82
+ >
83
+ <path
84
+ d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"
85
+ fill="currentColor"
86
+ />
87
+ </svg>
88
+ );
89
+
90
+ const HeartIcon = () => (
91
+ <svg
92
+ viewBox="0 0 24 24"
93
+ width="100%"
94
+ height="100%"
95
+ xmlns="http://www.w3.org/2000/svg"
96
+ >
97
+ <path
98
+ d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"
99
+ fill="currentColor"
100
+ />
101
+ </svg>
102
+ );
103
+
104
+ const Demo = () => {
105
+ return (
106
+ <div
107
+ style={{
108
+ padding: "20px",
109
+ fontFamily: "system-ui, sans-serif",
110
+ lineHeight: "1.6",
111
+ maxWidth: "800px",
112
+ }}
113
+ >
114
+ <h1>Text and Icon Combinations</h1>
115
+
116
+ <section style={{ marginBottom: "40px" }}>
117
+ <h2>Basic Icon + Text</h2>
118
+ <div
119
+ style={{
120
+ display: "flex",
121
+ flexDirection: "column",
122
+ gap: "10px",
123
+ }}
124
+ >
125
+ <Text>
126
+ <Icon>
127
+ <HomeIcon />
128
+ </Icon>
129
+ Home
130
+ </Text>
131
+
132
+ <Text>
133
+ <Icon>
134
+ <UserIcon />
135
+ </Icon>
136
+ Profile
137
+ </Text>
138
+
139
+ <Text>
140
+ <Icon>
141
+ <SettingsIcon />
142
+ </Icon>
143
+ Settings
144
+ </Text>
145
+ </div>
146
+ </section>
147
+
148
+ <section style={{ marginBottom: "40px" }}>
149
+ <h2>Text + Icon (Reversed Order)</h2>
150
+ <div
151
+ style={{
152
+ display: "flex",
153
+ flexDirection: "column",
154
+ gap: "10px",
155
+ }}
156
+ >
157
+ <Text>
158
+ Search
159
+ <Icon>
160
+ <SearchIcon />
161
+ </Icon>
162
+ </Text>
163
+
164
+ <Text>
165
+ Favorites
166
+ <Icon>
167
+ <StarIcon />
168
+ </Icon>
169
+ </Text>
170
+
171
+ <Text>
172
+ Liked
173
+ <Icon>
174
+ <HeartIcon />
175
+ </Icon>
176
+ </Text>
177
+ </div>
178
+ </section>
179
+
180
+ <section style={{ marginBottom: "40px" }}>
181
+ <h2>Multiple Icons</h2>
182
+ <div
183
+ style={{
184
+ display: "flex",
185
+ flexDirection: "column",
186
+ gap: "10px",
187
+ }}
188
+ >
189
+ <Text>
190
+ <Icon>
191
+ <HomeIcon />
192
+ </Icon>
193
+ Left and right
194
+ <Icon>
195
+ <StarIcon />
196
+ </Icon>
197
+ </Text>
198
+
199
+ <Text>
200
+ <Icon>
201
+ <UserIcon />
202
+ </Icon>
203
+ <Icon>
204
+ <SettingsIcon />
205
+ </Icon>
206
+ Two on the left
207
+ </Text>
208
+ </div>
209
+ </section>
210
+
211
+ <section style={{ marginBottom: "40px" }}>
212
+ <h2>Different Font Sizes</h2>
213
+ <div
214
+ style={{
215
+ display: "flex",
216
+ flexDirection: "column",
217
+ gap: "15px",
218
+ }}
219
+ >
220
+ <Text style={{ fontSize: "12px" }}>
221
+ <Icon>
222
+ <HomeIcon />
223
+ </Icon>
224
+ Small text with icon
225
+ </Text>
226
+
227
+ <Text style={{ fontSize: "16px" }}>
228
+ <Icon>
229
+ <UserIcon />
230
+ </Icon>
231
+ Normal text with icon
232
+ </Text>
233
+
234
+ <Text style={{ fontSize: "24px" }}>
235
+ <Icon>
236
+ <SettingsIcon />
237
+ </Icon>
238
+ Large text with icon
239
+ </Text>
240
+
241
+ <Text style={{ fontSize: "32px" }}>
242
+ <Icon>
243
+ <StarIcon />
244
+ </Icon>
245
+ Extra large text
246
+ </Text>
247
+ </div>
248
+ </section>
249
+
250
+ <section style={{ marginBottom: "40px" }}>
251
+ <h2>Colored Examples</h2>
252
+ <div
253
+ style={{
254
+ display: "flex",
255
+ flexDirection: "column",
256
+ gap: "10px",
257
+ }}
258
+ >
259
+ <Text style={{ color: "blue" }}>
260
+ <Icon>
261
+ <HomeIcon />
262
+ </Icon>
263
+ Blue home link
264
+ </Text>
265
+
266
+ <Text style={{ color: "green" }}>
267
+ <Icon>
268
+ <UserIcon />
269
+ </Icon>
270
+ Green user profile
271
+ </Text>
272
+
273
+ <Text style={{ color: "red" }}>
274
+ <Icon>
275
+ <HeartIcon />
276
+ </Icon>
277
+ Red heart favorite
278
+ </Text>
279
+
280
+ <Text style={{ color: "purple" }}>
281
+ <Icon>
282
+ <StarIcon />
283
+ </Icon>
284
+ Purple star rating
285
+ </Text>
286
+ </div>
287
+ </section>
288
+
289
+ <section style={{ marginBottom: "40px" }}>
290
+ <h2>Interactive Buttons</h2>
291
+ <div
292
+ style={{
293
+ display: "flex",
294
+ flexDirection: "column",
295
+ gap: "10px",
296
+ }}
297
+ >
298
+ <button
299
+ style={{
300
+ padding: "10px 15px",
301
+ border: "1px solid #ccc",
302
+ borderRadius: "4px",
303
+ background: "white",
304
+ cursor: "pointer",
305
+ fontSize: "14px",
306
+ }}
307
+ >
308
+ <Text>
309
+ <Icon>
310
+ <SearchIcon />
311
+ </Icon>
312
+ Search Files
313
+ </Text>
314
+ </button>
315
+
316
+ <button
317
+ style={{
318
+ padding: "10px 15px",
319
+ border: "none",
320
+ borderRadius: "4px",
321
+ background: "#007bff",
322
+ color: "white",
323
+ cursor: "pointer",
324
+ fontSize: "14px",
325
+ }}
326
+ >
327
+ <Text>
328
+ <Icon>
329
+ <UserIcon />
330
+ </Icon>
331
+ Create Account
332
+ </Text>
333
+ </button>
334
+
335
+ <button
336
+ style={{
337
+ padding: "10px 15px",
338
+ border: "1px solid #dc3545",
339
+ borderRadius: "4px",
340
+ background: "transparent",
341
+ color: "#dc3545",
342
+ cursor: "pointer",
343
+ fontSize: "14px",
344
+ }}
345
+ >
346
+ <Text>
347
+ <Icon>
348
+ <HeartIcon />
349
+ </Icon>
350
+ Add to Favorites
351
+ </Text>
352
+ </button>
353
+ </div>
354
+ </section>
355
+
356
+ <section style={{ marginBottom: "40px" }}>
357
+ <h2>Navigation Menu Style</h2>
358
+ <nav
359
+ style={{
360
+ background: "#f8f9fa",
361
+ padding: "20px",
362
+ borderRadius: "8px",
363
+ }}
364
+ >
365
+ <div
366
+ style={{
367
+ display: "flex",
368
+ flexDirection: "column",
369
+ gap: "15px",
370
+ }}
371
+ >
372
+ <Text
373
+ style={{
374
+ cursor: "pointer",
375
+ padding: "8px 12px",
376
+ borderRadius: "4px",
377
+ transition: "background-color 0.2s",
378
+ }}
379
+ >
380
+ <Icon>
381
+ <HomeIcon />
382
+ </Icon>
383
+ Dashboard
384
+ </Text>
385
+
386
+ <Text
387
+ style={{
388
+ cursor: "pointer",
389
+ padding: "8px 12px",
390
+ borderRadius: "4px",
391
+ background: "#007bff",
392
+ color: "white",
393
+ }}
394
+ >
395
+ <Icon>
396
+ <UserIcon />
397
+ </Icon>
398
+ Users
399
+ </Text>
400
+
401
+ <Text
402
+ style={{
403
+ cursor: "pointer",
404
+ padding: "8px 12px",
405
+ borderRadius: "4px",
406
+ }}
407
+ >
408
+ <Icon>
409
+ <SettingsIcon />
410
+ </Icon>
411
+ Settings
412
+ </Text>
413
+ </div>
414
+ </nav>
415
+ </section>
416
+
417
+ <section>
418
+ <h2>Inline Text with Icons</h2>
419
+ <p style={{ fontSize: "16px", lineHeight: "1.6" }}>
420
+ Welcome to our platform! Click on the{" "}
421
+ <Text>
422
+ <Icon>
423
+ <HomeIcon />
424
+ </Icon>
425
+ home
426
+ </Text>{" "}
427
+ button to return to the dashboard, or visit your{" "}
428
+ <Text>
429
+ <Icon>
430
+ <UserIcon />
431
+ </Icon>
432
+ profile
433
+ </Text>{" "}
434
+ to update your settings. Don't forget to{" "}
435
+ <Text>
436
+ <Icon>
437
+ <StarIcon />
438
+ </Icon>
439
+ star
440
+ </Text>{" "}
441
+ your favorite items and{" "}
442
+ <Text>
443
+ <Icon>
444
+ <HeartIcon />
445
+ </Icon>
446
+ like
447
+ </Text>{" "}
448
+ the content you enjoy. Use the{" "}
449
+ <Text>
450
+ <Icon>
451
+ <SearchIcon />
452
+ </Icon>
453
+ search
454
+ </Text>{" "}
455
+ feature to find what you're looking for quickly.
456
+ </p>
457
+ </section>
458
+ </div>
459
+ );
460
+ };
461
+
462
+ render(<Demo />, document.getElementById("app"));
463
+ </script>
464
+ </body>
465
+ </html>
@@ -0,0 +1,48 @@
1
+ import.meta.css = /* css */ `
2
+ :root {
3
+ --navi-icon-align-y: center;
4
+ }
5
+
6
+ .navi_text {
7
+ display: inline-flex;
8
+ align-items: baseline;
9
+ gap: 0.1em;
10
+ }
11
+
12
+ .navi_icon {
13
+ --align-y: var(--navi-icon-align-y, center);
14
+
15
+ display: inline-flex;
16
+ width: 1em;
17
+ height: 1em;
18
+ flex-shrink: 0;
19
+ align-self: var(--align-y);
20
+ line-height: 1em;
21
+ }
22
+ `;
23
+
24
+ export const Text = ({ children, ...rest }) => {
25
+ return (
26
+ <span {...rest} className="navi_text">
27
+ {children}
28
+ </span>
29
+ );
30
+ };
31
+
32
+ const alignYMapping = {
33
+ start: "flex-start",
34
+ center: "center",
35
+ end: "flex-end",
36
+ };
37
+ export const Icon = ({ alignY, style, children, ...rest }) => {
38
+ const innerStyle = { ...style };
39
+ if (alignY !== "center") {
40
+ innerStyle["--align-y"] = alignYMapping[alignY];
41
+ }
42
+
43
+ return (
44
+ <span {...rest} className="navi_icon" style={innerStyle}>
45
+ {children}
46
+ </span>
47
+ );
48
+ };