@cfasim-ui/docs 0.3.11
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/LICENSE +201 -0
- package/charts/ChartMenu/ChartMenu.vue +140 -0
- package/charts/ChartMenu/download.ts +44 -0
- package/charts/ChartTooltip/ChartTooltip.vue +97 -0
- package/charts/ChoroplethMap/ChoroplethMap.md +398 -0
- package/charts/ChoroplethMap/ChoroplethMap.vue +777 -0
- package/charts/ChoroplethMap/hsaMapping.ts +4116 -0
- package/charts/DataTable/DataTable.md +143 -0
- package/charts/DataTable/DataTable.vue +277 -0
- package/charts/LineChart/LineChart.md +472 -0
- package/charts/LineChart/LineChart.vue +1216 -0
- package/charts/index.ts +23 -0
- package/charts/tooltip-position.ts +49 -0
- package/components/Box/Box.md +49 -0
- package/components/Box/Box.vue +52 -0
- package/components/Button/Button.md +67 -0
- package/components/Button/Button.vue +81 -0
- package/components/Expander/Expander.md +34 -0
- package/components/Expander/Expander.vue +95 -0
- package/components/Hint/Hint.md +29 -0
- package/components/Hint/Hint.vue +83 -0
- package/components/Icon/Icon.md +67 -0
- package/components/Icon/Icon.vue +112 -0
- package/components/LightDarkToggle/LightDarkToggle.vue +49 -0
- package/components/NumberInput/NumberInput.md +305 -0
- package/components/NumberInput/NumberInput.vue +531 -0
- package/components/SelectBox/SelectBox.md +110 -0
- package/components/SelectBox/SelectBox.vue +195 -0
- package/components/SidebarLayout/SidebarLayout.md +104 -0
- package/components/SidebarLayout/SidebarLayout.vue +466 -0
- package/components/Spinner/Spinner.md +51 -0
- package/components/Spinner/Spinner.vue +55 -0
- package/components/TextInput/TextInput.md +82 -0
- package/components/TextInput/TextInput.vue +94 -0
- package/components/Toggle/Toggle.md +81 -0
- package/components/Toggle/Toggle.vue +81 -0
- package/components/index.ts +15 -0
- package/index.json +121 -0
- package/package.json +24 -0
- package/pyodide/index.ts +7 -0
- package/pyodide/pyodide.worker.ts +233 -0
- package/pyodide/pyodideWorkerApi.ts +102 -0
- package/pyodide/useModel.ts +86 -0
- package/pyodide/vitePlugin.js +51 -0
- package/shared/ModelOutput.ts +88 -0
- package/shared/csv.ts +22 -0
- package/shared/index.ts +24 -0
- package/shared/transferUtils.ts +126 -0
- package/shared/useUrlParams.ts +296 -0
- package/theme/all.js +5 -0
- package/theme/base.css +176 -0
- package/theme/cfasim.css +3 -0
- package/theme/theme.css +113 -0
- package/theme/themes/cdc.css +22 -0
- package/theme/utilities.css +518 -0
- package/wasm/index.ts +2 -0
- package/wasm/useModel.ts +53 -0
- package/wasm/vitePlugin.js +35 -0
- package/wasm/wasm.worker.ts +74 -0
- package/wasm/wasmWorkerApi.ts +38 -0
package/charts/index.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export {
|
|
2
|
+
default as LineChart,
|
|
3
|
+
type Series,
|
|
4
|
+
type Area,
|
|
5
|
+
type AreaSection,
|
|
6
|
+
} from "./LineChart/LineChart.vue";
|
|
7
|
+
export {
|
|
8
|
+
default as ChoroplethMap,
|
|
9
|
+
type GeoType,
|
|
10
|
+
type StateData,
|
|
11
|
+
type ChoroplethColorScale,
|
|
12
|
+
type ThresholdStop,
|
|
13
|
+
type CategoricalStop,
|
|
14
|
+
} from "./ChoroplethMap/ChoroplethMap.vue";
|
|
15
|
+
export { default as ChartTooltip } from "./ChartTooltip/ChartTooltip.vue";
|
|
16
|
+
export {
|
|
17
|
+
default as DataTable,
|
|
18
|
+
type TableData,
|
|
19
|
+
type TableRecord,
|
|
20
|
+
type ColumnAlign,
|
|
21
|
+
type ColumnConfig,
|
|
22
|
+
type ColumnWidth,
|
|
23
|
+
} from "./DataTable/DataTable.vue";
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export type TooltipClamp = "none" | "chart" | "window";
|
|
2
|
+
|
|
3
|
+
const GAP = 16;
|
|
4
|
+
const PAD = 8;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Computes a tooltip position in client coordinates, flipping to the opposite
|
|
8
|
+
* side of the pointer and clamping vertically when the preferred placement
|
|
9
|
+
* would overflow the clamp boundary.
|
|
10
|
+
*
|
|
11
|
+
* The tooltip is assumed to be anchored with `transform: translateY(-50%)`,
|
|
12
|
+
* so `top` is the vertical center.
|
|
13
|
+
*/
|
|
14
|
+
export function placeTooltip(
|
|
15
|
+
clientX: number,
|
|
16
|
+
centerY: number,
|
|
17
|
+
tipW: number,
|
|
18
|
+
tipH: number,
|
|
19
|
+
clamp: TooltipClamp,
|
|
20
|
+
chartRect?: DOMRect,
|
|
21
|
+
): { left: number; top: number } {
|
|
22
|
+
if (clamp === "none") {
|
|
23
|
+
return { left: clientX + GAP, top: centerY };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const bounds =
|
|
27
|
+
clamp === "chart" && chartRect
|
|
28
|
+
? {
|
|
29
|
+
left: chartRect.left,
|
|
30
|
+
right: chartRect.right,
|
|
31
|
+
top: chartRect.top,
|
|
32
|
+
bottom: chartRect.bottom,
|
|
33
|
+
}
|
|
34
|
+
: {
|
|
35
|
+
left: 0,
|
|
36
|
+
right: window.innerWidth,
|
|
37
|
+
top: 0,
|
|
38
|
+
bottom: window.innerHeight,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const flip = clientX + GAP + tipW > bounds.right - PAD;
|
|
42
|
+
const left = flip ? clientX - GAP - tipW : clientX + GAP;
|
|
43
|
+
const halfH = tipH / 2;
|
|
44
|
+
const top = Math.min(
|
|
45
|
+
Math.max(centerY, bounds.top + PAD + halfH),
|
|
46
|
+
bounds.bottom - PAD - halfH,
|
|
47
|
+
);
|
|
48
|
+
return { left, top };
|
|
49
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Box
|
|
2
|
+
|
|
3
|
+
A colored container for callouts, alerts, and grouped content.
|
|
4
|
+
|
|
5
|
+
## Examples
|
|
6
|
+
|
|
7
|
+
### Variants
|
|
8
|
+
|
|
9
|
+
<ComponentDemo>
|
|
10
|
+
<Box variant="info">This is an info box.</Box>
|
|
11
|
+
<Box variant="success">This is a success box.</Box>
|
|
12
|
+
<Box variant="warning">This is a warning box.</Box>
|
|
13
|
+
<Box variant="error">This is an error box.</Box>
|
|
14
|
+
|
|
15
|
+
<template #code>
|
|
16
|
+
|
|
17
|
+
```vue
|
|
18
|
+
<Box variant="info">This is an info box.</Box>
|
|
19
|
+
<Box variant="success">This is a success box.</Box>
|
|
20
|
+
<Box variant="warning">This is a warning box.</Box>
|
|
21
|
+
<Box variant="error">This is an error box.</Box>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
</template>
|
|
25
|
+
</ComponentDemo>
|
|
26
|
+
|
|
27
|
+
### Custom colors
|
|
28
|
+
|
|
29
|
+
<ComponentDemo>
|
|
30
|
+
<Box bg-color="#f0e6ff" text-color="#4a1d96">Custom purple box</Box>
|
|
31
|
+
|
|
32
|
+
<template #code>
|
|
33
|
+
|
|
34
|
+
```vue
|
|
35
|
+
<Box bg-color="#f0e6ff" text-color="#4a1d96">Custom purple box</Box>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
</template>
|
|
39
|
+
</ComponentDemo>
|
|
40
|
+
|
|
41
|
+
## Props
|
|
42
|
+
|
|
43
|
+
| Prop | Type | Required | Default |
|
|
44
|
+
|------|------|----------|---------|
|
|
45
|
+
| `variant` | `BoxVariant` | No | — |
|
|
46
|
+
| `bgColor` | `string` | No | — |
|
|
47
|
+
| `textColor` | `string` | No | — |
|
|
48
|
+
| `role` | `string` | No | — |
|
|
49
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
export type BoxVariant = "info" | "success" | "warning" | "error";
|
|
3
|
+
|
|
4
|
+
defineProps<{
|
|
5
|
+
variant?: BoxVariant;
|
|
6
|
+
bgColor?: string;
|
|
7
|
+
textColor?: string;
|
|
8
|
+
role?: string;
|
|
9
|
+
}>();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template>
|
|
13
|
+
<div
|
|
14
|
+
class="box"
|
|
15
|
+
:class="variant ? `box-${variant}` : undefined"
|
|
16
|
+
:style="{
|
|
17
|
+
backgroundColor: bgColor,
|
|
18
|
+
color: textColor,
|
|
19
|
+
}"
|
|
20
|
+
:role="role"
|
|
21
|
+
>
|
|
22
|
+
<slot />
|
|
23
|
+
</div>
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<style scoped>
|
|
27
|
+
.box {
|
|
28
|
+
padding: 0.75em 1.25em;
|
|
29
|
+
border-radius: 0.375em;
|
|
30
|
+
font-size: var(--font-size-sm);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.box-info {
|
|
34
|
+
background-color: var(--color-box-info-bg);
|
|
35
|
+
color: var(--color-box-info-text);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.box-success {
|
|
39
|
+
background-color: var(--color-box-success-bg);
|
|
40
|
+
color: var(--color-box-success-text);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.box-warning {
|
|
44
|
+
background-color: var(--color-box-warning-bg);
|
|
45
|
+
color: var(--color-box-warning-text);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.box-error {
|
|
49
|
+
background-color: var(--color-box-error-bg);
|
|
50
|
+
color: var(--color-box-error-text);
|
|
51
|
+
}
|
|
52
|
+
</style>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Button
|
|
2
|
+
|
|
3
|
+
A button for triggering actions. Supports primary and secondary variants.
|
|
4
|
+
|
|
5
|
+
Built on [reka-ui Primitive](https://reka-ui.com/docs/utilities/primitive), so it supports `as` and `asChild` for rendering as different elements.
|
|
6
|
+
|
|
7
|
+
## Examples
|
|
8
|
+
|
|
9
|
+
### Variants
|
|
10
|
+
|
|
11
|
+
<ComponentDemo>
|
|
12
|
+
<Button>Primary</Button>
|
|
13
|
+
<Button variant="secondary">Secondary</Button>
|
|
14
|
+
|
|
15
|
+
<template #code>
|
|
16
|
+
|
|
17
|
+
```vue
|
|
18
|
+
<Button>Primary</Button>
|
|
19
|
+
<Button variant="secondary">Secondary</Button>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
</template>
|
|
23
|
+
</ComponentDemo>
|
|
24
|
+
|
|
25
|
+
### Disabled
|
|
26
|
+
|
|
27
|
+
<ComponentDemo>
|
|
28
|
+
<Button disabled>Disabled</Button>
|
|
29
|
+
<Button variant="secondary" disabled>Disabled</Button>
|
|
30
|
+
|
|
31
|
+
<template #code>
|
|
32
|
+
|
|
33
|
+
```vue
|
|
34
|
+
<Button disabled>Disabled</Button>
|
|
35
|
+
<Button variant="secondary" disabled>Disabled</Button>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
</template>
|
|
39
|
+
</ComponentDemo>
|
|
40
|
+
|
|
41
|
+
### With label prop
|
|
42
|
+
|
|
43
|
+
<ComponentDemo>
|
|
44
|
+
<Button label="Click me" />
|
|
45
|
+
|
|
46
|
+
<template #code>
|
|
47
|
+
|
|
48
|
+
```vue
|
|
49
|
+
<Button label="Click me" />
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
</template>
|
|
53
|
+
</ComponentDemo>
|
|
54
|
+
|
|
55
|
+
## Props
|
|
56
|
+
|
|
57
|
+
| Prop | Type | Required | Default |
|
|
58
|
+
|------|------|----------|---------|
|
|
59
|
+
| `label` | `string` | No | — |
|
|
60
|
+
| `variant` | `"primary" \| "secondary"` | No | `"primary"` |
|
|
61
|
+
|
|
62
|
+
## Events
|
|
63
|
+
|
|
64
|
+
| Event | Payload |
|
|
65
|
+
|-------|---------|
|
|
66
|
+
| `click` | `event: MouseEvent` |
|
|
67
|
+
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { Primitive } from "reka-ui";
|
|
3
|
+
import type { PrimitiveProps } from "reka-ui";
|
|
4
|
+
|
|
5
|
+
interface Props extends PrimitiveProps {
|
|
6
|
+
label?: string;
|
|
7
|
+
variant?: "primary" | "secondary";
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
withDefaults(defineProps<Props>(), {
|
|
11
|
+
as: "button",
|
|
12
|
+
variant: "primary",
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
defineEmits<{
|
|
16
|
+
click: [event: MouseEvent];
|
|
17
|
+
}>();
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<template>
|
|
21
|
+
<Primitive
|
|
22
|
+
class="button"
|
|
23
|
+
:data-variant="variant"
|
|
24
|
+
:as="as"
|
|
25
|
+
:as-child="asChild"
|
|
26
|
+
@click="$emit('click', $event)"
|
|
27
|
+
>
|
|
28
|
+
<slot>{{ label }}</slot>
|
|
29
|
+
</Primitive>
|
|
30
|
+
</template>
|
|
31
|
+
|
|
32
|
+
<style scoped>
|
|
33
|
+
.button {
|
|
34
|
+
display: inline-flex;
|
|
35
|
+
border: none;
|
|
36
|
+
align-items: center;
|
|
37
|
+
justify-content: center;
|
|
38
|
+
align-self: flex-start;
|
|
39
|
+
flex-shrink: 0;
|
|
40
|
+
min-height: 2.5em;
|
|
41
|
+
padding: 0 1em;
|
|
42
|
+
font-size: var(--font-size-sm);
|
|
43
|
+
font-weight: 500;
|
|
44
|
+
border-radius: 0.375em;
|
|
45
|
+
background-color: var(--color-primary);
|
|
46
|
+
color: var(--color-text-on-primary);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.button:hover {
|
|
50
|
+
cursor: pointer;
|
|
51
|
+
background-color: var(--color-primary-hover);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.button:active {
|
|
55
|
+
background-color: var(--color-primary-active);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.button:focus-visible {
|
|
59
|
+
outline: none;
|
|
60
|
+
box-shadow: var(--shadow-focus);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.button:disabled {
|
|
64
|
+
opacity: 0.5;
|
|
65
|
+
cursor: not-allowed;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.button[data-variant="secondary"] {
|
|
69
|
+
background-color: transparent;
|
|
70
|
+
color: var(--color-primary);
|
|
71
|
+
border: 1px solid var(--color-primary);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.button[data-variant="secondary"]:hover {
|
|
75
|
+
background-color: color-mix(in srgb, var(--color-primary) 10%, transparent);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.button[data-variant="secondary"]:active {
|
|
79
|
+
background-color: color-mix(in srgb, var(--color-primary) 15%, transparent);
|
|
80
|
+
}
|
|
81
|
+
</style>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Expander
|
|
2
|
+
|
|
3
|
+
A collapsible section that toggles content visibility.
|
|
4
|
+
|
|
5
|
+
## Examples
|
|
6
|
+
|
|
7
|
+
<ComponentDemo>
|
|
8
|
+
<Expander label="Show advanced options">
|
|
9
|
+
<p style="margin: 0">Here is the hidden content.</p>
|
|
10
|
+
</Expander>
|
|
11
|
+
|
|
12
|
+
<template #code>
|
|
13
|
+
|
|
14
|
+
```vue
|
|
15
|
+
<Expander label="Show advanced options">
|
|
16
|
+
<p>Here is the hidden content.</p>
|
|
17
|
+
</Expander>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
</template>
|
|
21
|
+
</ComponentDemo>
|
|
22
|
+
|
|
23
|
+
## Model
|
|
24
|
+
|
|
25
|
+
| Name | Type |
|
|
26
|
+
|------|------|
|
|
27
|
+
| `v-model:open` | `boolean` |
|
|
28
|
+
|
|
29
|
+
## Props
|
|
30
|
+
|
|
31
|
+
| Prop | Type | Required | Default |
|
|
32
|
+
|------|------|----------|---------|
|
|
33
|
+
| `label` | `string` | No | — |
|
|
34
|
+
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
CollapsibleRoot,
|
|
4
|
+
CollapsibleTrigger,
|
|
5
|
+
CollapsibleContent,
|
|
6
|
+
} from "reka-ui";
|
|
7
|
+
|
|
8
|
+
const open = defineModel<boolean>("open", { default: false });
|
|
9
|
+
|
|
10
|
+
defineProps<{
|
|
11
|
+
label?: string;
|
|
12
|
+
}>();
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<template>
|
|
16
|
+
<CollapsibleRoot v-model:open="open" class="expander">
|
|
17
|
+
<CollapsibleTrigger class="expander-trigger">
|
|
18
|
+
<span class="expander-caret" :class="{ open }" />
|
|
19
|
+
<slot name="label">{{ label }}</slot>
|
|
20
|
+
</CollapsibleTrigger>
|
|
21
|
+
<CollapsibleContent class="expander-content">
|
|
22
|
+
<slot />
|
|
23
|
+
</CollapsibleContent>
|
|
24
|
+
</CollapsibleRoot>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<style scoped>
|
|
28
|
+
.expander-trigger {
|
|
29
|
+
display: flex;
|
|
30
|
+
align-items: center;
|
|
31
|
+
gap: 0.5em;
|
|
32
|
+
width: 100%;
|
|
33
|
+
padding: 0.5em 0;
|
|
34
|
+
background: none;
|
|
35
|
+
border: none;
|
|
36
|
+
cursor: pointer;
|
|
37
|
+
font: inherit;
|
|
38
|
+
font-size: var(--font-size-sm);
|
|
39
|
+
font-weight: 600;
|
|
40
|
+
text-transform: uppercase;
|
|
41
|
+
letter-spacing: 0.05em;
|
|
42
|
+
color: var(--color-text-secondary);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.expander-trigger:hover {
|
|
46
|
+
color: var(--color-text);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.expander-caret {
|
|
50
|
+
display: inline-block;
|
|
51
|
+
width: 0;
|
|
52
|
+
height: 0;
|
|
53
|
+
border-left: 0.35em solid currentColor;
|
|
54
|
+
border-top: 0.3em solid transparent;
|
|
55
|
+
border-bottom: 0.3em solid transparent;
|
|
56
|
+
transition: transform 0.15s;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.expander-caret.open {
|
|
60
|
+
transform: rotate(90deg);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.expander-content {
|
|
64
|
+
overflow: hidden;
|
|
65
|
+
display: flex;
|
|
66
|
+
flex-direction: column;
|
|
67
|
+
gap: 0.75em;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.expander-content[data-state="open"] {
|
|
71
|
+
animation: slideDown 200ms ease-out;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.expander-content[data-state="closed"] {
|
|
75
|
+
animation: slideUp 200ms ease-out;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@keyframes slideDown {
|
|
79
|
+
from {
|
|
80
|
+
height: 0;
|
|
81
|
+
}
|
|
82
|
+
to {
|
|
83
|
+
height: var(--reka-collapsible-content-height);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@keyframes slideUp {
|
|
88
|
+
from {
|
|
89
|
+
height: var(--reka-collapsible-content-height);
|
|
90
|
+
}
|
|
91
|
+
to {
|
|
92
|
+
height: 0;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
</style>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Hint
|
|
2
|
+
|
|
3
|
+
An info icon that shows a tooltip on hover. Used alongside form labels to provide additional context.
|
|
4
|
+
|
|
5
|
+
## Examples
|
|
6
|
+
|
|
7
|
+
<ComponentDemo>
|
|
8
|
+
<span style="display: flex; align-items: center; gap: 8px;">
|
|
9
|
+
Population size <Hint text="The total number of individuals in the simulation." />
|
|
10
|
+
</span>
|
|
11
|
+
|
|
12
|
+
<template #code>
|
|
13
|
+
|
|
14
|
+
```vue
|
|
15
|
+
<span style="display: flex; align-items: center; gap: 8px;">
|
|
16
|
+
Population size
|
|
17
|
+
<Hint text="The total number of individuals in the simulation." />
|
|
18
|
+
</span>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
</template>
|
|
22
|
+
</ComponentDemo>
|
|
23
|
+
|
|
24
|
+
## Props
|
|
25
|
+
|
|
26
|
+
| Prop | Type | Required | Default |
|
|
27
|
+
|------|------|----------|---------|
|
|
28
|
+
| `text` | `string` | Yes | — |
|
|
29
|
+
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
TooltipArrow,
|
|
4
|
+
TooltipContent,
|
|
5
|
+
TooltipPortal,
|
|
6
|
+
TooltipProvider,
|
|
7
|
+
TooltipRoot,
|
|
8
|
+
TooltipTrigger,
|
|
9
|
+
} from "reka-ui";
|
|
10
|
+
import Icon from "../Icon/Icon.vue";
|
|
11
|
+
|
|
12
|
+
defineProps<{
|
|
13
|
+
text: string;
|
|
14
|
+
}>();
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<template>
|
|
18
|
+
<TooltipProvider>
|
|
19
|
+
<TooltipRoot :delay-duration="0" disable-closing-trigger>
|
|
20
|
+
<TooltipTrigger as-child>
|
|
21
|
+
<button
|
|
22
|
+
type="button"
|
|
23
|
+
class="HintTrigger"
|
|
24
|
+
aria-label="More info"
|
|
25
|
+
@pointerdown.prevent
|
|
26
|
+
>
|
|
27
|
+
<Icon icon="help" :size="16" />
|
|
28
|
+
</button>
|
|
29
|
+
</TooltipTrigger>
|
|
30
|
+
<TooltipPortal>
|
|
31
|
+
<TooltipContent class="HintContent" side="top" :side-offset="4">
|
|
32
|
+
{{ text }}
|
|
33
|
+
<TooltipArrow class="HintArrow" :width="10" :height="5" />
|
|
34
|
+
</TooltipContent>
|
|
35
|
+
</TooltipPortal>
|
|
36
|
+
</TooltipRoot>
|
|
37
|
+
</TooltipProvider>
|
|
38
|
+
</template>
|
|
39
|
+
|
|
40
|
+
<style scoped>
|
|
41
|
+
.HintTrigger {
|
|
42
|
+
display: inline-flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
justify-content: center;
|
|
45
|
+
width: 1.25em;
|
|
46
|
+
height: 1.25em;
|
|
47
|
+
padding: 0;
|
|
48
|
+
margin: 0;
|
|
49
|
+
border: none;
|
|
50
|
+
border-radius: 50%;
|
|
51
|
+
background: transparent;
|
|
52
|
+
color: var(--color-text-secondary);
|
|
53
|
+
cursor: pointer;
|
|
54
|
+
flex-shrink: 0;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.HintTrigger:hover {
|
|
58
|
+
color: var(--color-text);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.HintTrigger:focus-visible {
|
|
62
|
+
outline: none;
|
|
63
|
+
box-shadow: var(--shadow-focus);
|
|
64
|
+
}
|
|
65
|
+
</style>
|
|
66
|
+
|
|
67
|
+
<style>
|
|
68
|
+
.HintContent {
|
|
69
|
+
max-width: 15rem;
|
|
70
|
+
padding: 0.5em 0.75em;
|
|
71
|
+
font-size: var(--font-size-xs);
|
|
72
|
+
line-height: 1.4;
|
|
73
|
+
color: var(--color-bg-0);
|
|
74
|
+
background-color: var(--color-text);
|
|
75
|
+
border-radius: 0.25em;
|
|
76
|
+
box-shadow: var(--shadow-md);
|
|
77
|
+
z-index: 100;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.HintArrow {
|
|
81
|
+
fill: var(--color-text);
|
|
82
|
+
}
|
|
83
|
+
</style>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Icon
|
|
2
|
+
|
|
3
|
+
Renders a [Material Symbols Outlined](https://fonts.google.com/icons) icon.
|
|
4
|
+
|
|
5
|
+
## Examples
|
|
6
|
+
|
|
7
|
+
### Sizes
|
|
8
|
+
|
|
9
|
+
<ComponentDemo>
|
|
10
|
+
<Icon icon="help" size="sm" aria-label="help" />
|
|
11
|
+
<Icon icon="help" size="md" aria-label="help" />
|
|
12
|
+
<Icon icon="help" size="lg" aria-label="help" />
|
|
13
|
+
|
|
14
|
+
<template #code>
|
|
15
|
+
|
|
16
|
+
```vue
|
|
17
|
+
<Icon icon="help" size="sm" aria-label="help" />
|
|
18
|
+
<Icon icon="help" size="md" aria-label="help" />
|
|
19
|
+
<Icon icon="help" size="lg" aria-label="help" />
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
</template>
|
|
23
|
+
</ComponentDemo>
|
|
24
|
+
|
|
25
|
+
### Filled
|
|
26
|
+
|
|
27
|
+
<ComponentDemo>
|
|
28
|
+
<Icon icon="favorite" size="lg" aria-label="favorite" />
|
|
29
|
+
<Icon icon="favorite" size="lg" :fill="true" aria-label="favorite filled" />
|
|
30
|
+
|
|
31
|
+
<template #code>
|
|
32
|
+
|
|
33
|
+
```vue
|
|
34
|
+
<Icon icon="favorite" size="lg" aria-label="favorite" />
|
|
35
|
+
<Icon icon="favorite" size="lg" :fill="true" aria-label="favorite filled" />
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
</template>
|
|
39
|
+
</ComponentDemo>
|
|
40
|
+
|
|
41
|
+
### Inline in text
|
|
42
|
+
|
|
43
|
+
<ComponentDemo>
|
|
44
|
+
<p style="margin: 0">Click the <Icon icon="help" size="sm" :inline="true" aria-label="help" /> icon for more info.</p>
|
|
45
|
+
|
|
46
|
+
<template #code>
|
|
47
|
+
|
|
48
|
+
```vue
|
|
49
|
+
<p>Click the <Icon icon="help" size="sm" :inline="true" aria-label="help" /> icon for more info.</p>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
</template>
|
|
53
|
+
</ComponentDemo>
|
|
54
|
+
|
|
55
|
+
## Props
|
|
56
|
+
|
|
57
|
+
| Prop | Type | Required | Default |
|
|
58
|
+
|------|------|----------|---------|
|
|
59
|
+
| `icon` | `string` | Yes | — |
|
|
60
|
+
| `size` | `IconSize \| number` | No | `"md"` |
|
|
61
|
+
| `fill` | `boolean` | No | `false` |
|
|
62
|
+
| `weight` | `number` | No | — |
|
|
63
|
+
| `grade` | `number` | No | — |
|
|
64
|
+
| `decorative` | `boolean` | No | `true` |
|
|
65
|
+
| `ariaLabel` | `string` | No | — |
|
|
66
|
+
| `inline` | `boolean` | No | `false` |
|
|
67
|
+
|