@octane-xplat/ui 0.4.0 → 0.6.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/README.md +3 -0
- package/dist/native/Absolute.native.tsrx.js +43 -0
- package/dist/native/Accordion.native.tsrx.js +75 -0
- package/dist/native/ActivityIndicator.native.tsrx.js +35 -0
- package/dist/native/Alert.native.tsrx.js +74 -0
- package/dist/native/Avatar.native.tsrx.js +76 -0
- package/dist/native/AvatarGroup.native.tsrx.js +84 -0
- package/dist/native/Badge.native.tsrx.js +29 -0
- package/dist/native/Banner.native.tsrx.js +80 -0
- package/dist/native/Breadcrumb.native.tsrx.js +66 -0
- package/dist/native/Button.native.tsrx.js +62 -0
- package/dist/native/CameraView.native.tsrx.js +165 -0
- package/dist/native/Card.native.tsrx.js +64 -0
- package/dist/native/Checkbox.native.tsrx.js +58 -0
- package/dist/native/CheckboxGroup.native.tsrx.js +70 -0
- package/dist/native/Chip.native.tsrx.js +83 -0
- package/dist/native/Collapsible.native.tsrx.js +74 -0
- package/dist/native/CommandPalette.native.tsrx.js +143 -0
- package/dist/native/ContextMenu.native.tsrx.js +140 -0
- package/dist/native/Drawer.native.tsrx.js +60 -0
- package/dist/native/DropdownMenu.native.tsrx.js +155 -0
- package/dist/native/Empty.native.tsrx.js +82 -0
- package/dist/native/FieldGroup.native.tsrx.js +39 -0
- package/dist/native/FormField.native.tsrx.js +53 -0
- package/dist/native/{ui8.js → Grid.native.tsrx.js} +19 -8
- package/dist/native/{ui56.js → Heading.native.tsrx.js} +2 -2
- package/dist/native/{ui55.js → Icon.native.tsrx.js} +4 -4
- package/dist/native/{ui29.js → Image.native.tsrx.js} +4 -4
- package/dist/native/InputNumber.native.tsrx.js +146 -0
- package/dist/native/InputRating.native.tsrx.js +74 -0
- package/dist/native/InputTags.native.tsrx.js +131 -0
- package/dist/native/Kbd.native.tsrx.js +29 -0
- package/dist/native/{ui48.js → KeyboardAvoiding.native.tsrx.js} +1 -1
- package/dist/native/{ui17.js → Link.native.tsrx.js} +1 -1
- package/dist/native/{ui52.js → Meter.native.tsrx.js} +2 -2
- package/dist/native/{ui22.js → NavLink.native.tsrx.js} +3 -3
- package/dist/native/NavigationMenu.native.tsrx.js +67 -0
- package/dist/native/{ui35.js → Overlay.native.tsrx.js} +3 -3
- package/dist/native/Pager.native.tsrx.js +282 -0
- package/dist/native/Pagination.native.tsrx.js +107 -0
- package/dist/native/PinInput.native.tsrx.js +94 -0
- package/dist/native/{ui38.js → Popover.native.tsrx.js} +5 -5
- package/dist/native/{ui16.js → Pressable.native.tsrx.js} +21 -15
- package/dist/native/ProgressGroup.native.tsrx.js +66 -0
- package/dist/native/RadioGroup.native.tsrx.js +85 -0
- package/dist/native/{ui15.js → RichText.native.tsrx.js} +15 -22
- package/dist/native/Row.native.tsrx.js +98 -0
- package/dist/native/{ui47.js → SafeArea.native.tsrx.js} +2 -2
- package/dist/native/{ui43.js → Screen.native.tsrx.js} +3 -3
- package/dist/native/{ui26.js → ScrollBox.native.tsrx.js} +1 -1
- package/dist/native/ScrollView.native.tsrx.js +233 -0
- package/dist/native/SearchInput.native.tsrx.js +151 -0
- package/dist/native/SegmentedControl.native.tsrx.js +75 -0
- package/dist/native/Select.native.tsrx.js +202 -0
- package/dist/native/Separator.native.tsrx.js +25 -0
- package/dist/native/{ui60.js → Sheet.native.tsrx.js} +15 -7
- package/dist/native/Skeleton.native.tsrx.js +28 -0
- package/dist/native/Slider.native.tsrx.js +98 -0
- package/dist/native/{ui13.js → Spacer.native.tsrx.js} +2 -2
- package/dist/native/{ui9.js → Stack.native.tsrx.js} +20 -9
- package/dist/native/Stepper.native.tsrx.js +75 -0
- package/dist/native/Switch.native.tsrx.js +33 -0
- package/dist/native/Table.native.tsrx.js +103 -0
- package/dist/native/Tabs.native.tsrx.js +163 -0
- package/dist/native/{ui14.js → Text.native.tsrx.js} +19 -3
- package/dist/native/{ui24.js → TextArea.native.tsrx.js} +19 -17
- package/dist/native/{ui23.js → TextInput.native.tsrx.js} +21 -16
- package/dist/native/Timeline.native.tsrx.js +112 -0
- package/dist/native/Tree.native.tsrx.js +140 -0
- package/dist/native/User.native.tsrx.js +95 -0
- package/dist/native/Video.native.tsrx.js +248 -0
- package/dist/native/{ui6.js → View.native.tsrx.js} +39 -25
- package/dist/native/WebView.native.tsrx.js +110 -0
- package/dist/native/aliases.native.tsrx.js +38 -0
- package/dist/native/android/BottomNavigationView.android.tsrx.js +171 -0
- package/dist/native/android/CircularProgressIndicator.android.tsrx.js +27 -0
- package/dist/native/{ui49.js → android/DrawerLayout.android.tsrx.js} +5 -7
- package/dist/native/android/MaterialDialog.android.tsrx.js +62 -0
- package/dist/native/android/MaterialSwitch.android.tsrx.js +28 -0
- package/dist/native/android/RecyclerView.android.tsrx.js +248 -0
- package/dist/native/android/SeekBar.android.tsrx.js +34 -0
- package/dist/native/android/index.js +9 -0
- package/dist/native/android/openModal.android.js +39 -0
- package/dist/native/camera-permission.native.js +47 -0
- package/dist/native/child-array.js +15 -0
- package/dist/native/{ui3.js → escape-props.native.js} +22 -1
- package/dist/native/icons.js +25 -0
- package/dist/native/{ui11.js → ios/LiquidGlass.ios.tsrx.js} +4 -4
- package/dist/native/{ui12.js → ios/LiquidGlassContainer.ios.tsrx.js} +4 -4
- package/dist/native/ios/SideDrawer.ios.tsrx.js +64 -0
- package/dist/native/{ui50.js → ios/UIActivityIndicatorView.ios.tsrx.js} +5 -5
- package/dist/native/{ui32.js → ios/UIModal.ios.tsrx.js} +10 -6
- package/dist/native/{ui53.js → ios/UISlider.ios.tsrx.js} +5 -5
- package/dist/native/{ui45.js → ios/UISwitch.ios.tsrx.js} +5 -5
- package/dist/native/ios/UITabBar.ios.tsrx.js +166 -0
- package/dist/native/ios/UITableView.ios.tsrx.js +270 -0
- package/dist/native/ios/index.js +11 -0
- package/dist/native/{ui33.js → ios/openModal.ios.js} +5 -4
- package/dist/native/modal-presenter.native.js +19 -0
- package/dist/native/native/index.js +4 -0
- package/dist/native/octane-client-build.json +1 -1
- package/dist/native/pan.native.tsrx.js +66 -0
- package/dist/native/platform.native.js +10 -0
- package/dist/native/refresh-metrics.js +9 -0
- package/dist/native/refresh.native.js +177 -0
- package/dist/native/{ui34.js → root-layout.native.js} +6 -1
- package/dist/native/{ui21.js → route.native.js} +96 -12
- package/dist/native/sheet-detents.native.js +102 -0
- package/dist/native/{ui61.js → sheet-service.native.js} +19 -9
- package/dist/native/sheet-snap.js +35 -0
- package/dist/native/text-write.native.js +27 -0
- package/dist/native/theme/status-bar-scheme.native.js +17 -0
- package/dist/{web/ui29.js → native/theme/theme-scheme.js} +2 -2
- package/dist/native/toast-anchor.native.tsrx.js +185 -0
- package/dist/native/translate.native.js +11 -0
- package/dist/native/ui.js +93 -52
- package/dist/native/use-back.native.tsrx.js +9 -0
- package/dist/native/useMeasure.native.tsrx.js +64 -0
- package/dist/native/video-chrome.native.tsrx.js +365 -0
- package/dist/web/Absolute.web.tsrx.js +47 -0
- package/dist/web/Accordion.web.tsrx.js +85 -0
- package/dist/web/{ui46.js → ActivityIndicator.web.tsrx.js} +1 -1
- package/dist/web/Alert.web.tsrx.js +79 -0
- package/dist/web/Avatar.web.tsrx.js +106 -0
- package/dist/web/AvatarGroup.web.tsrx.js +108 -0
- package/dist/web/Badge.web.tsrx.js +37 -0
- package/dist/web/Banner.web.tsrx.js +79 -0
- package/dist/web/Breadcrumb.web.tsrx.js +135 -0
- package/dist/web/Button.web.tsrx.js +45 -0
- package/dist/web/CameraView.web.tsrx.js +310 -0
- package/dist/web/Card.web.tsrx.js +73 -0
- package/dist/web/Checkbox.web.tsrx.js +89 -0
- package/dist/web/CheckboxGroup.web.tsrx.js +79 -0
- package/dist/web/Chip.web.tsrx.js +64 -0
- package/dist/web/Collapsible.web.tsrx.js +94 -0
- package/dist/web/CommandPalette.web.tsrx.js +125 -0
- package/dist/web/ContextMenu.web.tsrx.js +154 -0
- package/dist/web/{ui44.js → Drawer.web.tsrx.js} +13 -9
- package/dist/web/DropdownMenu.web.tsrx.js +162 -0
- package/dist/web/Empty.web.tsrx.js +89 -0
- package/dist/web/FieldGroup.web.tsrx.js +57 -0
- package/dist/web/FormField.web.tsrx.js +92 -0
- package/dist/web/Grid.web.tsrx.js +65 -0
- package/dist/web/{ui52.js → Heading.web.tsrx.js} +2 -2
- package/dist/web/Icon.web.tsrx.js +273 -0
- package/dist/web/{ui25.js → Image.web.tsrx.js} +2 -2
- package/dist/web/InputNumber.web.tsrx.js +99 -0
- package/dist/web/InputRating.web.tsrx.js +72 -0
- package/dist/web/InputTags.web.tsrx.js +122 -0
- package/dist/web/Kbd.web.tsrx.js +37 -0
- package/dist/web/{ui48.js → Meter.web.tsrx.js} +1 -1
- package/dist/web/{ui19.js → NavLink.web.tsrx.js} +1 -1
- package/dist/web/NavigationMenu.web.tsrx.js +118 -0
- package/dist/web/{ui31.js → Overlay.web.tsrx.js} +2 -2
- package/dist/web/Pager.web.tsrx.js +337 -0
- package/dist/web/Pagination.web.tsrx.js +80 -0
- package/dist/web/PinInput.web.tsrx.js +72 -0
- package/dist/web/{ui33.js → Popover.web.tsrx.js} +3 -3
- package/dist/web/{ui15.js → Pressable.web.tsrx.js} +68 -95
- package/dist/web/ProgressGroup.web.tsrx.js +109 -0
- package/dist/web/RadioGroup.web.tsrx.js +69 -0
- package/dist/web/{ui14.js → RichText.web.tsrx.js} +2 -2
- package/dist/web/Row.web.tsrx.js +250 -0
- package/dist/web/{ui42.js → SafeArea.web.tsrx.js} +1 -1
- package/dist/web/{ui38.js → Screen.web.tsrx.js} +1 -1
- package/dist/web/{ui24.js → ScrollBox.web.tsrx.js} +1 -1
- package/dist/web/ScrollView.web.tsrx.js +388 -0
- package/dist/web/SearchInput.web.tsrx.js +137 -0
- package/dist/web/SegmentedControl.web.tsrx.js +75 -0
- package/dist/web/Select.web.tsrx.js +149 -0
- package/dist/web/Separator.web.tsrx.js +42 -0
- package/dist/web/Sheet.web.tsrx.js +81 -0
- package/dist/web/Skeleton.web.tsrx.js +56 -0
- package/dist/web/Slider.web.tsrx.js +97 -0
- package/dist/web/{ui12.js → Spacer.web.tsrx.js} +1 -1
- package/dist/web/Stack.web.tsrx.js +47 -0
- package/dist/web/Stepper.web.tsrx.js +65 -0
- package/dist/web/Switch.web.tsrx.js +59 -0
- package/dist/web/Table.web.tsrx.js +161 -0
- package/dist/web/{ui39.js → Tabs.web.tsrx.js} +33 -16
- package/dist/web/{ui13.js → Text.web.tsrx.js} +79 -46
- package/dist/web/{ui21.js → TextArea.web.tsrx.js} +4 -4
- package/dist/web/{ui20.js → TextInput.web.tsrx.js} +8 -8
- package/dist/web/Timeline.web.tsrx.js +172 -0
- package/dist/web/Tree.web.tsrx.js +146 -0
- package/dist/web/User.web.tsrx.js +116 -0
- package/dist/web/Video.web.tsrx.js +400 -0
- package/dist/web/View.web.tsrx.js +250 -0
- package/dist/web/WebView.web.tsrx.js +235 -0
- package/dist/web/aliases.web.tsrx.js +24 -0
- package/dist/web/{ui35.js → anim.web.tsrx.js} +3 -2
- package/dist/web/child-array.js +15 -0
- package/dist/web/icons.js +25 -0
- package/dist/web/octane-client-build.json +1 -1
- package/dist/web/pan.web.tsrx.js +66 -0
- package/dist/web/platform.web.js +9 -0
- package/dist/web/refresh-metrics.js +9 -0
- package/dist/web/refresh.web.js +133 -0
- package/dist/web/{ui18.js → route.web.js} +14 -2
- package/dist/web/sheet-detents.web.js +103 -0
- package/dist/web/{ui58.js → sheet-service.web.js} +5 -1
- package/dist/web/sheet-snap.js +35 -0
- package/dist/{native/ui31.js → web/theme/theme-scheme.js} +2 -2
- package/dist/web/toast-anchor.web.tsrx.js +142 -0
- package/dist/web/transform.web.js +43 -0
- package/dist/web/translate.web.js +13 -0
- package/dist/web/ui.js +91 -51
- package/dist/web/use-back.web.tsrx.js +9 -0
- package/dist/web/useMeasure.web.tsrx.js +50 -0
- package/dist/web/video-chrome.web.tsrx.js +207 -0
- package/dist/web/web/Hoverable.web.tsrx.js +150 -0
- package/dist/web/web/Tooltip.web.tsrx.js +183 -0
- package/dist/web/web/index.js +3 -0
- package/package.json +34 -3
- package/src/theme/tokens.css +1599 -194
- package/types/android.d.ts +53 -0
- package/types/index.d.ts +39 -14
- package/types/index.native.d.ts +273 -0
- package/types/index.web.d.ts +272 -0
- package/types/ios.d.ts +59 -0
- package/types/native.d.ts +5 -0
- package/types/props.d.ts +989 -44
- package/types/web.d.ts +17 -0
- package/dist/native/ui10.js +0 -32
- package/dist/native/ui25.js +0 -141
- package/dist/native/ui27.js +0 -61
- package/dist/native/ui39.js +0 -105
- package/dist/native/ui4.js +0 -24
- package/dist/native/ui44.js +0 -267
- package/dist/native/ui54.js +0 -17
- package/dist/native/ui57.js +0 -14
- package/dist/native/ui7.js +0 -52
- package/dist/web/ui10.js +0 -46
- package/dist/web/ui11.js +0 -42
- package/dist/web/ui22.js +0 -108
- package/dist/web/ui23.js +0 -96
- package/dist/web/ui26.js +0 -45
- package/dist/web/ui3.js +0 -31
- package/dist/web/ui30.js +0 -34
- package/dist/web/ui34.js +0 -70
- package/dist/web/ui40.js +0 -43
- package/dist/web/ui43.js +0 -42
- package/dist/web/ui49.js +0 -47
- package/dist/web/ui5.js +0 -168
- package/dist/web/ui50.js +0 -17
- package/dist/web/ui51.js +0 -149
- package/dist/web/ui53.js +0 -17
- package/dist/web/ui57.js +0 -44
- package/dist/web/ui6.js +0 -94
- package/dist/web/ui7.js +0 -62
- package/dist/web/ui8.js +0 -46
- package/dist/web/ui9.js +0 -46
- /package/dist/native/{ui20.js → RouteHost.native.tsrx.js} +0 -0
- /package/dist/native/{ui40.js → anim.native.tsrx.js} +0 -0
- /package/dist/native/{ui2.js → cx.js} +0 -0
- /package/dist/native/{ui5.js → layout-child.native.js} +0 -0
- /package/dist/native/{ui51.js → meter-math.js} +0 -0
- /package/dist/native/{ui36.js → platformProps.native.js} +0 -0
- /package/dist/native/{ui37.js → popover-position.js} +0 -0
- /package/dist/native/{ui19.js → route-table.js} +0 -0
- /package/dist/native/{ui46.js → safeAreaInsets.native.tsrx.js} +0 -0
- /package/dist/native/{ui18.js → stacks.native.js} +0 -0
- /package/dist/native/{ui58.js → store.js} +0 -0
- /package/dist/native/{ui41.js → styled.native.tsrx.js} +0 -0
- /package/dist/native/{ui28.js → svg.native.js} +0 -0
- /package/dist/native/{ui30.js → theme/colorScheme.native.js} +0 -0
- /package/dist/native/{ui59.js → use-store.native.tsrx.js} +0 -0
- /package/dist/native/{ui42.js → windows.native.js} +0 -0
- /package/dist/web/{ui16.js → Link.web.tsrx.js} +0 -0
- /package/dist/web/{ui28.js → cx.js} +0 -0
- /package/dist/web/{ui2.js → escape-props.web.js} +0 -0
- /package/dist/web/{ui4.js → layout-child.web.js} +0 -0
- /package/dist/web/{ui47.js → meter-math.js} +0 -0
- /package/dist/web/{ui45.js → platformProps.web.js} +0 -0
- /package/dist/web/{ui32.js → popover-position.js} +0 -0
- /package/dist/web/{ui17.js → route-table.js} +0 -0
- /package/dist/web/{ui41.js → safeAreaInsets.web.tsrx.js} +0 -0
- /package/dist/web/{ui54.js → stacks.web.js} +0 -0
- /package/dist/web/{ui55.js → store.js} +0 -0
- /package/dist/web/{ui36.js → styled.web.tsrx.js} +0 -0
- /package/dist/web/{ui27.js → theme/colorScheme.web.js} +0 -0
- /package/dist/web/{ui56.js → use-store.web.tsrx.js} +0 -0
- /package/dist/web/{ui37.js → windows.web.js} +0 -0
package/src/theme/tokens.css
CHANGED
|
@@ -3,10 +3,22 @@
|
|
|
3
3
|
|
|
4
4
|
:root,
|
|
5
5
|
.ns-root {
|
|
6
|
-
--color-primary: #
|
|
7
|
-
|
|
6
|
+
--color-primary: #171717;
|
|
7
|
+
/* Token names double as the future Tailwind theme keys: text-onprimary
|
|
8
|
+
resolves --color-onprimary, bg-danger resolves --color-danger. Keep
|
|
9
|
+
class-name segments and var-name segments identical. */
|
|
10
|
+
--color-onprimary: #fafafa;
|
|
8
11
|
--color-surface: #ffffff;
|
|
9
|
-
--color-
|
|
12
|
+
--color-surface-secondary: #fafafa;
|
|
13
|
+
--color-text: #0a0a0a;
|
|
14
|
+
--color-text-secondary: #666666;
|
|
15
|
+
--color-border: #eaeaea;
|
|
16
|
+
--color-border-strong: #d4d4d4;
|
|
17
|
+
--color-danger: #dc2626;
|
|
18
|
+
/* Family lists are deliberately generic. Apps override these with their
|
|
19
|
+
web @font-face family and the platform's registered native name. */
|
|
20
|
+
--font-sans: system-ui, sans-serif;
|
|
21
|
+
--font-mono: ui-monospace, monospace;
|
|
10
22
|
--space-4: 16px;
|
|
11
23
|
/* Corner scale — rounded-rectangle radii. Smooth (squircle) corners are
|
|
12
24
|
the default corner treatment: every class that consumes a token also
|
|
@@ -20,8 +32,62 @@
|
|
|
20
32
|
|
|
21
33
|
.ns-dark,
|
|
22
34
|
.dark {
|
|
23
|
-
--color-
|
|
24
|
-
--color-
|
|
35
|
+
--color-primary: #ededed;
|
|
36
|
+
--color-onprimary: #171717;
|
|
37
|
+
--color-surface: #0a0a0a;
|
|
38
|
+
--color-surface-secondary: #141414;
|
|
39
|
+
--color-text: #ededed;
|
|
40
|
+
--color-text-secondary: #a1a1a1;
|
|
41
|
+
--color-border: #2e2e2e;
|
|
42
|
+
--color-border-strong: #4a4a4a;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* xplat-web-only:start — DOM normalization. NativeScript is the reference
|
|
46
|
+
box model: dip sizes are outer boxes, and a border paints from
|
|
47
|
+
width+color alone. The DOM's UA stylesheet diverges on both counts, so
|
|
48
|
+
normalize the deltas once instead of patching individual rules:
|
|
49
|
+
- border-box keeps padding/borders inside declared sizes (a 40dip box
|
|
50
|
+
is 40px, not 40px + padding + border).
|
|
51
|
+
- border-width 0 + border-style solid makes the DOM behave like native:
|
|
52
|
+
any shared border-*-width declaration paints on both targets — the
|
|
53
|
+
DOM's initial border-width is `medium`, so style alone would draw
|
|
54
|
+
phantom ~3px edges wherever a rule sets only one side's width.
|
|
55
|
+
- <img> is a leaf, not inline text (no baseline descender gap).
|
|
56
|
+
- .vx-app columns are flex like their native screen containers. */
|
|
57
|
+
*,
|
|
58
|
+
*::before,
|
|
59
|
+
*::after {
|
|
60
|
+
box-sizing: border-box;
|
|
61
|
+
}
|
|
62
|
+
* {
|
|
63
|
+
border-width: 0;
|
|
64
|
+
border-style: solid;
|
|
65
|
+
}
|
|
66
|
+
img {
|
|
67
|
+
display: block;
|
|
68
|
+
}
|
|
69
|
+
.vx-app {
|
|
70
|
+
display: flex;
|
|
71
|
+
flex-direction: column;
|
|
72
|
+
}
|
|
73
|
+
/* Native has no scroll chaining — a ScrollView just bounces inside
|
|
74
|
+
itself because the parent is never a scroller. contain is the DOM
|
|
75
|
+
equivalent: scroll stays in the leaf it started in. */
|
|
76
|
+
.vx-scroll {
|
|
77
|
+
overscroll-behavior: contain;
|
|
78
|
+
}
|
|
79
|
+
/* xplat-web-only:end */
|
|
80
|
+
|
|
81
|
+
/* Shared normalization — NS FlexboxLayout defaults flex children to
|
|
82
|
+
shrink:1 with NO min-content floor (its shrink pass clamps at
|
|
83
|
+
effectiveMinWidth/Height = the explicit min-* prop, default 0), so an
|
|
84
|
+
overflowing column crushes intrinsic children toward zero where the
|
|
85
|
+
web stops at min-content. RN's Yoga defaults flexShrink:0 for the same
|
|
86
|
+
reason — do the same on both engines. `*` is zero-specificity: flex-1
|
|
87
|
+
(the shorthand sets shrink:1) and .shrink still opt back in, and
|
|
88
|
+
truncation patterns pair them with min-w-0/min-h-0. */
|
|
89
|
+
* {
|
|
90
|
+
flex-shrink: 0;
|
|
25
91
|
}
|
|
26
92
|
|
|
27
93
|
/* vocabulary base styles */
|
|
@@ -54,8 +120,17 @@
|
|
|
54
120
|
display: flex;
|
|
55
121
|
flex-direction: column;
|
|
56
122
|
}
|
|
57
|
-
/*
|
|
58
|
-
|
|
123
|
+
/* Self-drawn drawer — shared geometry. Native grid children overlay the
|
|
124
|
+
cell (panel pins left via horizontalAlignment in the leaf); DOM
|
|
125
|
+
positioning extras are web-only below. */
|
|
126
|
+
.vx-drawer-backdrop {
|
|
127
|
+
background-color: rgba(0, 0, 0, 0.4);
|
|
128
|
+
}
|
|
129
|
+
.vx-drawer-panel {
|
|
130
|
+
width: 280px;
|
|
131
|
+
background-color: var(--color-surface);
|
|
132
|
+
}
|
|
133
|
+
/* xplat-web-only:start */
|
|
59
134
|
.vx-drawer {
|
|
60
135
|
display: flex;
|
|
61
136
|
flex-direction: row;
|
|
@@ -70,7 +145,6 @@
|
|
|
70
145
|
.vx-drawer-backdrop {
|
|
71
146
|
position: absolute;
|
|
72
147
|
inset: 0;
|
|
73
|
-
background: rgba(15, 23, 42, 0.35);
|
|
74
148
|
}
|
|
75
149
|
.vx-drawer-panel {
|
|
76
150
|
position: absolute;
|
|
@@ -78,9 +152,7 @@
|
|
|
78
152
|
top: 0;
|
|
79
153
|
bottom: 0;
|
|
80
154
|
left: 0;
|
|
81
|
-
width: 280px;
|
|
82
155
|
overflow: auto;
|
|
83
|
-
background: var(--color-surface);
|
|
84
156
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
|
|
85
157
|
}
|
|
86
158
|
/* xplat-web-only:end */
|
|
@@ -123,9 +195,6 @@
|
|
|
123
195
|
.vx-pressable:active {
|
|
124
196
|
opacity: 0.85;
|
|
125
197
|
}
|
|
126
|
-
.vx-pressable-no-feedback:active {
|
|
127
|
-
opacity: 1;
|
|
128
|
-
}
|
|
129
198
|
/* native press feedback (NS pseudo — dead rule on web, and vice versa) */
|
|
130
199
|
.vx-pressable:pressed {
|
|
131
200
|
opacity: 0.85;
|
|
@@ -140,7 +209,7 @@
|
|
|
140
209
|
.vx-overlay-shade {
|
|
141
210
|
position: absolute;
|
|
142
211
|
inset: 0;
|
|
143
|
-
background-color: rgba(0, 0, 0, 0.
|
|
212
|
+
background-color: rgba(0, 0, 0, 0.4);
|
|
144
213
|
}
|
|
145
214
|
|
|
146
215
|
.vx-overlay-content {
|
|
@@ -156,6 +225,18 @@
|
|
|
156
225
|
background-color: transparent;
|
|
157
226
|
}
|
|
158
227
|
|
|
228
|
+
.vx-tooltip {
|
|
229
|
+
padding: 4px 8px;
|
|
230
|
+
border-width: 1px;
|
|
231
|
+
border-color: var(--color-border);
|
|
232
|
+
border-radius: var(--radius-sm);
|
|
233
|
+
corner-shape: squircle;
|
|
234
|
+
background-color: var(--color-surface);
|
|
235
|
+
color: var(--color-text);
|
|
236
|
+
font-size: 12px;
|
|
237
|
+
line-height: 16px;
|
|
238
|
+
}
|
|
239
|
+
|
|
159
240
|
.vx-toast-host {
|
|
160
241
|
position: fixed;
|
|
161
242
|
z-index: 1002;
|
|
@@ -178,6 +259,39 @@
|
|
|
178
259
|
}
|
|
179
260
|
/* xplat-web-only:end */
|
|
180
261
|
|
|
262
|
+
/* Normalized OS-widget reset — TextInput/TextArea are real
|
|
263
|
+
<input>/<textarea>/TextField/TextView; the leaves emit vx-input/
|
|
264
|
+
vx-textarea unconditionally so the platform chrome is stripped before
|
|
265
|
+
app styles apply. On Android the transparent background replaces the
|
|
266
|
+
default EditText drawable (kills the Material underline); zero padding
|
|
267
|
+
removes native insets. Legitimate semantics — IME, secure entry,
|
|
268
|
+
selection, autofill, caret, focus — stay platform-native by design. */
|
|
269
|
+
.vx-input,
|
|
270
|
+
.vx-textarea {
|
|
271
|
+
padding: 0;
|
|
272
|
+
margin: 0;
|
|
273
|
+
border-width: 0;
|
|
274
|
+
background-color: transparent;
|
|
275
|
+
color: var(--color-text);
|
|
276
|
+
font-size: 14px;
|
|
277
|
+
/* NS placeholder color; web uses the ::placeholder pseudo below. */
|
|
278
|
+
placeholder-color: var(--color-text-secondary);
|
|
279
|
+
}
|
|
280
|
+
/* xplat-web-only:start — DOM-only reset: element UA chrome and the
|
|
281
|
+
focus outline (normalized to the same thin ring on both). */
|
|
282
|
+
.vx-input,
|
|
283
|
+
.vx-textarea {
|
|
284
|
+
appearance: none;
|
|
285
|
+
-webkit-appearance: none;
|
|
286
|
+
outline: none;
|
|
287
|
+
}
|
|
288
|
+
.vx-input:focus,
|
|
289
|
+
.vx-textarea:focus {
|
|
290
|
+
outline: 1px solid var(--color-primary);
|
|
291
|
+
outline-offset: -1px;
|
|
292
|
+
}
|
|
293
|
+
/* xplat-web-only:end */
|
|
294
|
+
|
|
181
295
|
/* auto-grow owns height — the manual resize handle has no native analog */
|
|
182
296
|
/* xplat-web-only:start */
|
|
183
297
|
.vx-textarea {
|
|
@@ -185,51 +299,93 @@
|
|
|
185
299
|
}
|
|
186
300
|
/* xplat-web-only:end */
|
|
187
301
|
|
|
188
|
-
/*
|
|
189
|
-
|
|
302
|
+
/* WebView chrome reset — the web leaf is a real <iframe>: strip the UA's
|
|
303
|
+
inset border and the inline-element baseline gap. WKWebView and
|
|
304
|
+
android.webkit.WebView ship chrome-free, so there is no native reset. */
|
|
190
305
|
/* xplat-web-only:start */
|
|
191
|
-
.vx-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
max-height: 90%;
|
|
195
|
-
padding: 24px;
|
|
196
|
-
border: 0;
|
|
197
|
-
border-radius: var(--radius-xl);
|
|
198
|
-
corner-shape: squircle;
|
|
199
|
-
color: var(--color-text);
|
|
200
|
-
background-color: var(--color-surface);
|
|
306
|
+
.vx-webview {
|
|
307
|
+
display: block;
|
|
308
|
+
border-width: 0;
|
|
201
309
|
}
|
|
310
|
+
/* xplat-web-only:end */
|
|
202
311
|
|
|
203
|
-
|
|
204
|
-
|
|
312
|
+
/* Video — surface-hosted leaf: the engine surface fills the frame and the
|
|
313
|
+
self-drawn transport layers stack on top in the same grid cell
|
|
314
|
+
(vx-stack). NS-side rules only — DOM resets sit in the web block. */
|
|
315
|
+
.vx-video {
|
|
316
|
+
background-color: #000;
|
|
205
317
|
}
|
|
206
318
|
|
|
207
|
-
.vx-
|
|
208
|
-
width:
|
|
209
|
-
|
|
319
|
+
.vx-video-centerbtn {
|
|
320
|
+
width: 56px;
|
|
321
|
+
height: 56px;
|
|
322
|
+
border-radius: 28px;
|
|
323
|
+
background-color: rgba(0, 0, 0, 0.55);
|
|
324
|
+
align-items: center;
|
|
325
|
+
justify-content: center;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.vx-video-bar {
|
|
329
|
+
background-color: rgba(0, 0, 0, 0.45);
|
|
330
|
+
padding: 4px 8px;
|
|
210
331
|
}
|
|
211
332
|
|
|
212
|
-
.vx-
|
|
333
|
+
.vx-video-btn {
|
|
334
|
+
padding: 4px;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/* Full-frame tap layer — hit target only, never paints. */
|
|
338
|
+
.vx-video-tap {
|
|
339
|
+
background-color: transparent;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
.vx-video-time {
|
|
343
|
+
color: #fff;
|
|
344
|
+
font-size: 11px;
|
|
345
|
+
min-width: 34px;
|
|
346
|
+
text-align: center;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/* xplat-web-only:start — the <video> element is inline and overlays would
|
|
350
|
+
otherwise swallow pointer events; native layers are hit-transparent by
|
|
351
|
+
default, so none of this exists on NS. */
|
|
352
|
+
.vx-video-surface {
|
|
353
|
+
display: block;
|
|
213
354
|
width: 100%;
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
355
|
+
height: 100%;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.vx-video-poster,
|
|
359
|
+
.vx-video-barwrap {
|
|
360
|
+
pointer-events: none;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
.vx-video-barwrap > * {
|
|
364
|
+
pointer-events: auto;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
.vx-video-poster {
|
|
368
|
+
object-fit: cover;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/* xplat-web-only:end */
|
|
372
|
+
|
|
373
|
+
/* CameraView — surface-hosted: the preview fills the frame; web shows it
|
|
374
|
+
through an object-fit:cover <video>. */
|
|
375
|
+
.vx-cameraview {
|
|
376
|
+
background-color: #000;
|
|
222
377
|
}
|
|
223
378
|
|
|
224
|
-
|
|
379
|
+
/* xplat-web-only:start */
|
|
380
|
+
.vx-cameraview-surface {
|
|
381
|
+
display: block;
|
|
225
382
|
width: 100%;
|
|
226
|
-
max-width: none;
|
|
227
383
|
height: 100%;
|
|
228
|
-
|
|
229
|
-
margin: 0;
|
|
230
|
-
border-radius: 0;
|
|
384
|
+
object-fit: cover;
|
|
231
385
|
}
|
|
386
|
+
/* xplat-web-only:end */
|
|
232
387
|
|
|
388
|
+
/* xplat-web-only:start */
|
|
233
389
|
/* Modal ROUTES (pushRoute presentation:'modal') — the URL stays underneath,
|
|
234
390
|
so the overlay is a fixed layer over the shell rather than a dialog. */
|
|
235
391
|
.vx-modalroute {
|
|
@@ -246,7 +402,7 @@
|
|
|
246
402
|
inset: 0;
|
|
247
403
|
border: 0;
|
|
248
404
|
padding: 0;
|
|
249
|
-
background: rgba(
|
|
405
|
+
background: rgba(0, 0, 0, 0.4);
|
|
250
406
|
cursor: default;
|
|
251
407
|
}
|
|
252
408
|
|
|
@@ -260,22 +416,70 @@
|
|
|
260
416
|
}
|
|
261
417
|
/* xplat-web-only:end */
|
|
262
418
|
|
|
263
|
-
/* xplat-web-only:start — placeholder pseudos are DOM-only
|
|
419
|
+
/* xplat-web-only:start — placeholder pseudos are DOM-only. Muted like
|
|
420
|
+
real placeholder text, not currentColor (a full-opacity hint reads as
|
|
421
|
+
a typed value); --placeholder-color is the per-field prop escape. */
|
|
264
422
|
input::placeholder,
|
|
265
423
|
textarea::placeholder {
|
|
266
|
-
color: var(--placeholder-color,
|
|
424
|
+
color: var(--placeholder-color, var(--color-text-secondary));
|
|
425
|
+
}
|
|
426
|
+
/* xplat-web-only:end */
|
|
427
|
+
|
|
428
|
+
/* xplat-web-only:start — form controls don't inherit the body font in the
|
|
429
|
+
DOM (UA stylesheet wins); without this they render in the UA face. */
|
|
430
|
+
input,
|
|
431
|
+
textarea,
|
|
432
|
+
select,
|
|
433
|
+
button {
|
|
434
|
+
font-family: inherit;
|
|
267
435
|
}
|
|
268
436
|
/* xplat-web-only:end */
|
|
269
437
|
|
|
270
|
-
/*
|
|
438
|
+
/* Self-drawn spinner — the border ring is shared (native rotates the
|
|
439
|
+
view via `animate`; DOM spins via the keyframes below). */
|
|
271
440
|
.vx-spinner {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
border: 2px solid currentColor;
|
|
441
|
+
width: 24px;
|
|
442
|
+
height: 24px;
|
|
443
|
+
border-width: 2px;
|
|
444
|
+
border-color: var(--color-text-secondary);
|
|
277
445
|
border-right-color: transparent;
|
|
278
446
|
border-radius: 50%;
|
|
447
|
+
}
|
|
448
|
+
/* Pull-to-refresh — the overlay strip hosting the spinner. Its height is
|
|
449
|
+
the default `refreshThreshold` (64px web / 64dip native); the leaf
|
|
450
|
+
translates it in/out — reveal math lives in refresh.*.ts. */
|
|
451
|
+
.vx-refresh {
|
|
452
|
+
display: flex;
|
|
453
|
+
flex-direction: column;
|
|
454
|
+
align-items: center;
|
|
455
|
+
justify-content: center;
|
|
456
|
+
height: 64px;
|
|
457
|
+
}
|
|
458
|
+
/* xplat-web-only:start — the DOM leaf needs explicit clipping plus the
|
|
459
|
+
absolute overlay; native clips via the wrapper grid
|
|
460
|
+
(clipsToBounds/ViewGroup) and stacks children in one cell. */
|
|
461
|
+
.vx-refresh-wrap {
|
|
462
|
+
position: relative;
|
|
463
|
+
overflow: hidden;
|
|
464
|
+
display: flex;
|
|
465
|
+
flex-direction: column;
|
|
466
|
+
}
|
|
467
|
+
.vx-refresh-wrap > .vx-scroll {
|
|
468
|
+
flex: 1;
|
|
469
|
+
min-height: 0;
|
|
470
|
+
}
|
|
471
|
+
.vx-refresh {
|
|
472
|
+
position: absolute;
|
|
473
|
+
top: 0;
|
|
474
|
+
left: 0;
|
|
475
|
+
right: 0;
|
|
476
|
+
}
|
|
477
|
+
/* xplat-web-only:end */
|
|
478
|
+
/* xplat-web-only:start — DOM needs an inline-block box + CSS animation;
|
|
479
|
+
the native leaf drives view.animate instead */
|
|
480
|
+
.vx-spinner {
|
|
481
|
+
display: inline-block;
|
|
482
|
+
box-sizing: border-box;
|
|
279
483
|
animation: vx-spinner-turn 0.8s linear infinite;
|
|
280
484
|
}
|
|
281
485
|
|
|
@@ -286,188 +490,1345 @@ textarea::placeholder {
|
|
|
286
490
|
}
|
|
287
491
|
/* xplat-web-only:end */
|
|
288
492
|
|
|
289
|
-
.
|
|
290
|
-
|
|
291
|
-
|
|
493
|
+
/* Self-drawn switch — flex track + thumb. `--on` flips justify-content,
|
|
494
|
+
which slides the thumb; identical geometry on web and native. */
|
|
495
|
+
.vx-switch {
|
|
496
|
+
width: 48px;
|
|
497
|
+
height: 28px;
|
|
498
|
+
padding-left: 3px;
|
|
499
|
+
padding-right: 3px;
|
|
500
|
+
border-radius: 14px;
|
|
501
|
+
background-color: var(--color-border);
|
|
502
|
+
justify-content: flex-start;
|
|
503
|
+
align-items: center;
|
|
292
504
|
}
|
|
293
|
-
.vx-
|
|
294
|
-
|
|
295
|
-
|
|
505
|
+
.vx-switch--on {
|
|
506
|
+
background-color: var(--color-primary);
|
|
507
|
+
justify-content: flex-end;
|
|
296
508
|
}
|
|
297
|
-
.vx-
|
|
298
|
-
|
|
299
|
-
|
|
509
|
+
.vx-switch-thumb {
|
|
510
|
+
width: 22px;
|
|
511
|
+
height: 22px;
|
|
512
|
+
border-radius: 50%;
|
|
513
|
+
background-color: var(--color-surface);
|
|
300
514
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
515
|
+
/* xplat-web-only:start — the DOM host is a div; flex + cursor live here */
|
|
516
|
+
.vx-switch {
|
|
517
|
+
display: flex;
|
|
518
|
+
cursor: pointer;
|
|
304
519
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
520
|
+
/* xplat-web-only:end */
|
|
521
|
+
|
|
522
|
+
/* Self-drawn slider — host is a grid (native) / relative div (web);
|
|
523
|
+
track + fill + thumb overlay the same box. */
|
|
524
|
+
.vx-slider {
|
|
525
|
+
height: 28px;
|
|
526
|
+
}
|
|
527
|
+
.vx-slider-track {
|
|
528
|
+
height: 4px;
|
|
529
|
+
border-radius: 2px;
|
|
530
|
+
background-color: var(--color-border);
|
|
531
|
+
vertical-align: middle;
|
|
532
|
+
}
|
|
533
|
+
.vx-slider-fill {
|
|
534
|
+
height: 4px;
|
|
535
|
+
border-radius: 2px;
|
|
536
|
+
background-color: var(--color-primary);
|
|
537
|
+
vertical-align: middle;
|
|
308
538
|
}
|
|
309
|
-
.vx-
|
|
310
|
-
|
|
311
|
-
|
|
539
|
+
.vx-slider-thumb {
|
|
540
|
+
width: 20px;
|
|
541
|
+
height: 20px;
|
|
542
|
+
border-radius: 50%;
|
|
543
|
+
background-color: var(--color-primary);
|
|
544
|
+
vertical-align: middle;
|
|
312
545
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
.vx-glass {
|
|
318
|
-
background-color: color-mix(in srgb, var(--color-surface) 30%, transparent);
|
|
319
|
-
border: 1px solid rgba(255, 255, 255, 0.25);
|
|
546
|
+
/* xplat-web-only:start — absolute positioning is DOM-only; native grid
|
|
547
|
+
children center via vertical-align and pin via margin-left. */
|
|
548
|
+
.vx-slider {
|
|
549
|
+
position: relative;
|
|
320
550
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
551
|
+
.vx-slider-track,
|
|
552
|
+
.vx-slider-fill {
|
|
553
|
+
position: absolute;
|
|
554
|
+
top: 50%;
|
|
555
|
+
left: 0;
|
|
556
|
+
right: 0;
|
|
557
|
+
transform: translateY(-50%);
|
|
328
558
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
559
|
+
.vx-slider-thumb {
|
|
560
|
+
position: absolute;
|
|
561
|
+
top: 50%;
|
|
562
|
+
transform: translate(-50%, -50%);
|
|
333
563
|
}
|
|
564
|
+
/* xplat-web-only:end */
|
|
334
565
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
566
|
+
/* xplat-web-only:start — Pager's web leaf is a mandatory scroll-snap row:
|
|
567
|
+
one page per item at 100% host width so scrollLeft / clientWidth is a
|
|
568
|
+
clean page index. Native pages are sized by the widget itself, so the
|
|
569
|
+
whole block is DOM-only. Scrollbar hidden (native has none); contain
|
|
570
|
+
keeps the swipe from chaining to a parent scroller, matching .vx-scroll. */
|
|
571
|
+
.vx-pager {
|
|
572
|
+
display: flex;
|
|
573
|
+
flex-direction: row;
|
|
574
|
+
overflow-x: auto;
|
|
575
|
+
overflow-y: hidden;
|
|
576
|
+
scroll-snap-type: x mandatory;
|
|
577
|
+
overscroll-behavior-x: contain;
|
|
578
|
+
scrollbar-width: none;
|
|
579
|
+
touch-action: pan-x;
|
|
580
|
+
}
|
|
581
|
+
.vx-pager::-webkit-scrollbar {
|
|
582
|
+
display: none;
|
|
583
|
+
}
|
|
584
|
+
.vx-pager-page {
|
|
585
|
+
flex: 0 0 100%;
|
|
586
|
+
min-width: 0;
|
|
587
|
+
display: flex;
|
|
588
|
+
flex-direction: column;
|
|
589
|
+
scroll-snap-align: start;
|
|
340
590
|
}
|
|
341
591
|
/* xplat-web-only:end */
|
|
342
592
|
|
|
343
|
-
/*
|
|
593
|
+
/* Phase-1 self-drawn components — functional geometry + token chrome only;
|
|
594
|
+
visual design is the app's job. */
|
|
344
595
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
* zero height. min-w-0/min-h-0 let a grow child shrink; shrink-0 protects
|
|
352
|
-
* a fixed-size child. All three are plain CSS on web. */
|
|
353
|
-
.min-w-0 {
|
|
354
|
-
min-width: 0;
|
|
355
|
-
}
|
|
356
|
-
.min-h-0 {
|
|
357
|
-
min-height: 0;
|
|
358
|
-
}
|
|
359
|
-
.shrink-0 {
|
|
360
|
-
flex-shrink: 0;
|
|
596
|
+
/* Button — row-direction pressable (vx-pressable already supplies display
|
|
597
|
+
and press feedback). */
|
|
598
|
+
.vx-button {
|
|
599
|
+
flex-direction: row;
|
|
600
|
+
align-items: center;
|
|
601
|
+
justify-content: center;
|
|
361
602
|
}
|
|
362
|
-
|
|
363
|
-
|
|
603
|
+
|
|
604
|
+
/* Collapsible/Accordion — column stacks. */
|
|
605
|
+
.vx-collapsible,
|
|
606
|
+
.vx-collapsible-content,
|
|
607
|
+
.vx-accordion,
|
|
608
|
+
.vx-accordion-item {
|
|
609
|
+
flex-direction: column;
|
|
364
610
|
}
|
|
365
|
-
|
|
611
|
+
|
|
612
|
+
/* Checkbox — 20px box + check glyph; --on fills with primary. */
|
|
613
|
+
.vx-checkbox-row {
|
|
614
|
+
flex-direction: row;
|
|
366
615
|
align-items: center;
|
|
367
616
|
}
|
|
368
|
-
.
|
|
617
|
+
.vx-checkbox {
|
|
618
|
+
width: 20px;
|
|
619
|
+
height: 20px;
|
|
620
|
+
border-width: 1px;
|
|
621
|
+
border-color: var(--color-border);
|
|
622
|
+
border-radius: var(--radius-sm);
|
|
623
|
+
align-items: center;
|
|
369
624
|
justify-content: center;
|
|
370
625
|
}
|
|
371
|
-
.
|
|
372
|
-
|
|
626
|
+
.vx-checkbox--on .vx-checkbox {
|
|
627
|
+
background-color: var(--color-primary);
|
|
628
|
+
border-color: var(--color-primary);
|
|
373
629
|
}
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
630
|
+
.vx-checkbox-check {
|
|
631
|
+
font-size: 14px;
|
|
632
|
+
line-height: 20px;
|
|
633
|
+
color: var(--color-onprimary);
|
|
377
634
|
}
|
|
378
|
-
.
|
|
379
|
-
|
|
635
|
+
.vx-checkbox-label {
|
|
636
|
+
margin-left: 8px;
|
|
637
|
+
}
|
|
638
|
+
.vx-checkbox--disabled {
|
|
639
|
+
opacity: 0.5;
|
|
380
640
|
}
|
|
381
641
|
|
|
382
|
-
/*
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
not a circle). Opt out per element with `corner-shape: round`. */
|
|
386
|
-
.rounded-sm {
|
|
387
|
-
border-radius: var(--radius-sm);
|
|
388
|
-
corner-shape: squircle;
|
|
642
|
+
/* Radio group — column/row of dot options. */
|
|
643
|
+
.vx-radio-group {
|
|
644
|
+
flex-direction: column;
|
|
389
645
|
}
|
|
390
|
-
.
|
|
391
|
-
|
|
392
|
-
corner-shape: squircle;
|
|
646
|
+
.vx-radio-group--row {
|
|
647
|
+
flex-direction: row;
|
|
393
648
|
}
|
|
394
|
-
.
|
|
395
|
-
|
|
396
|
-
|
|
649
|
+
.vx-radio-row {
|
|
650
|
+
flex-direction: row;
|
|
651
|
+
align-items: center;
|
|
397
652
|
}
|
|
398
|
-
.
|
|
399
|
-
|
|
400
|
-
|
|
653
|
+
.vx-radio {
|
|
654
|
+
width: 18px;
|
|
655
|
+
height: 18px;
|
|
656
|
+
border-width: 1px;
|
|
657
|
+
border-color: var(--color-border);
|
|
658
|
+
border-radius: 50%;
|
|
659
|
+
align-items: center;
|
|
660
|
+
justify-content: center;
|
|
401
661
|
}
|
|
402
|
-
.
|
|
403
|
-
border-
|
|
662
|
+
.vx-radio--on .vx-radio {
|
|
663
|
+
border-color: var(--color-primary);
|
|
404
664
|
}
|
|
405
|
-
|
|
406
|
-
|
|
665
|
+
.vx-radio-dot {
|
|
666
|
+
width: 8px;
|
|
667
|
+
height: 8px;
|
|
668
|
+
border-radius: 50%;
|
|
407
669
|
background-color: var(--color-primary);
|
|
408
670
|
}
|
|
409
|
-
.
|
|
410
|
-
|
|
411
|
-
}
|
|
412
|
-
.bg-danger {
|
|
413
|
-
background-color: #dc2626;
|
|
671
|
+
.vx-radio-label {
|
|
672
|
+
margin-left: 8px;
|
|
414
673
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
.shadow-2 {
|
|
418
|
-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
|
|
674
|
+
.vx-radio--disabled {
|
|
675
|
+
opacity: 0.5;
|
|
419
676
|
}
|
|
420
|
-
/* xplat-web-only:end */
|
|
421
677
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
678
|
+
/* SegmentedControl — equal-width segments in a rounded track; `--on`
|
|
679
|
+
raises the selected one. flex-basis is dead on NS (the shorthand parser
|
|
680
|
+
drops it and the standalone property isn't registered), so width:0 +
|
|
681
|
+
flex-grow:1 is what distributes segments equally on both engines. */
|
|
682
|
+
.vx-segmented {
|
|
683
|
+
flex-direction: row;
|
|
684
|
+
padding: 3px;
|
|
685
|
+
border-width: 1px;
|
|
686
|
+
border-color: var(--color-border);
|
|
427
687
|
border-radius: var(--radius-md);
|
|
428
688
|
corner-shape: squircle;
|
|
689
|
+
background-color: var(--color-surface-secondary);
|
|
690
|
+
color: var(--color-text);
|
|
429
691
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
692
|
+
.vx-segment {
|
|
693
|
+
flex-grow: 1;
|
|
694
|
+
width: 0;
|
|
695
|
+
flex-direction: row;
|
|
696
|
+
align-items: center;
|
|
697
|
+
justify-content: center;
|
|
698
|
+
padding-top: 6px;
|
|
699
|
+
padding-bottom: 6px;
|
|
700
|
+
padding-left: 10px;
|
|
701
|
+
padding-right: 10px;
|
|
702
|
+
border-radius: var(--radius-sm);
|
|
703
|
+
}
|
|
704
|
+
.vx-segment--on {
|
|
435
705
|
background-color: var(--color-surface);
|
|
436
|
-
color: var(--color-text);
|
|
437
706
|
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
707
|
+
.vx-segment-label {
|
|
708
|
+
font-size: 13px;
|
|
709
|
+
color: var(--color-text-secondary);
|
|
710
|
+
}
|
|
711
|
+
.vx-segment--on .vx-segment-label {
|
|
442
712
|
color: var(--color-text);
|
|
713
|
+
font-weight: 600;
|
|
443
714
|
}
|
|
444
|
-
|
|
715
|
+
.vx-segmented--disabled,
|
|
716
|
+
.vx-segment--disabled {
|
|
717
|
+
opacity: 0.5;
|
|
718
|
+
}
|
|
719
|
+
/* xplat-web-only:start — the DOM hosts are divs; flex + cursor live here */
|
|
720
|
+
.vx-segmented {
|
|
721
|
+
display: flex;
|
|
722
|
+
}
|
|
723
|
+
.vx-segment {
|
|
724
|
+
display: flex;
|
|
725
|
+
cursor: pointer;
|
|
726
|
+
user-select: none;
|
|
727
|
+
}
|
|
728
|
+
.vx-segment:focus {
|
|
729
|
+
outline: 1px solid var(--color-primary);
|
|
730
|
+
outline-offset: -1px;
|
|
731
|
+
}
|
|
732
|
+
.vx-segment--disabled {
|
|
733
|
+
cursor: default;
|
|
734
|
+
}
|
|
735
|
+
/* xplat-web-only:end */
|
|
736
|
+
|
|
737
|
+
/* SearchInput — chrome-reset field: bordered shell, leading glyph, the
|
|
738
|
+
field owns the remaining width, self-drawn clear. The web leaf hides the
|
|
739
|
+
engine's own search-cancel button so native's (hand-drawn) matches. */
|
|
740
|
+
.vx-search {
|
|
741
|
+
flex-direction: row;
|
|
742
|
+
align-items: center;
|
|
743
|
+
padding-top: 6px;
|
|
744
|
+
padding-bottom: 6px;
|
|
745
|
+
padding-left: 10px;
|
|
746
|
+
padding-right: 6px;
|
|
747
|
+
border-width: 1px;
|
|
748
|
+
border-color: var(--color-border);
|
|
749
|
+
border-radius: var(--radius-md);
|
|
750
|
+
corner-shape: squircle;
|
|
751
|
+
background-color: var(--color-surface);
|
|
752
|
+
color: var(--color-text);
|
|
753
|
+
}
|
|
754
|
+
.vx-search-icon {
|
|
755
|
+
color: var(--color-text-secondary);
|
|
756
|
+
}
|
|
757
|
+
.vx-search-field {
|
|
758
|
+
flex-grow: 1;
|
|
759
|
+
padding-left: 8px;
|
|
760
|
+
padding-right: 8px;
|
|
761
|
+
font-size: 14px;
|
|
762
|
+
color: var(--color-text);
|
|
763
|
+
}
|
|
764
|
+
.vx-search-clear {
|
|
765
|
+
width: 24px;
|
|
766
|
+
height: 24px;
|
|
767
|
+
border-radius: 9999px;
|
|
768
|
+
align-items: center;
|
|
769
|
+
justify-content: center;
|
|
770
|
+
background-color: var(--color-surface-secondary);
|
|
771
|
+
color: var(--color-text-secondary);
|
|
772
|
+
}
|
|
773
|
+
.vx-search--disabled {
|
|
774
|
+
opacity: 0.5;
|
|
775
|
+
}
|
|
776
|
+
/* xplat-web-only:start — the DOM host/field/buttons need display + the UA
|
|
777
|
+
reset; native's flexbox children carry these from the class already. */
|
|
778
|
+
.vx-search {
|
|
779
|
+
display: flex;
|
|
780
|
+
}
|
|
781
|
+
.vx-search-icon {
|
|
782
|
+
display: inline-flex;
|
|
783
|
+
flex: none;
|
|
784
|
+
}
|
|
785
|
+
.vx-search-field {
|
|
786
|
+
min-width: 0;
|
|
787
|
+
border: 0;
|
|
788
|
+
background: none;
|
|
789
|
+
outline: none;
|
|
790
|
+
appearance: none;
|
|
791
|
+
-webkit-appearance: none;
|
|
792
|
+
}
|
|
793
|
+
input.vx-search-field::-webkit-search-cancel-button {
|
|
794
|
+
display: none;
|
|
795
|
+
}
|
|
796
|
+
.vx-search-clear {
|
|
797
|
+
display: inline-flex;
|
|
798
|
+
border: 0;
|
|
799
|
+
padding: 0;
|
|
800
|
+
cursor: pointer;
|
|
801
|
+
}
|
|
802
|
+
/* xplat-web-only:end */
|
|
803
|
+
|
|
804
|
+
/* Anchored menus — panel + item rows (the Popover leaf positions it). */
|
|
805
|
+
.vx-menu {
|
|
806
|
+
min-width: 140px;
|
|
807
|
+
padding: 4px;
|
|
808
|
+
border-width: 1px;
|
|
809
|
+
border-color: var(--color-border);
|
|
810
|
+
border-radius: var(--radius-md);
|
|
811
|
+
corner-shape: squircle;
|
|
812
|
+
background-color: var(--color-surface);
|
|
813
|
+
color: var(--color-text);
|
|
814
|
+
}
|
|
815
|
+
.vx-menu-list {
|
|
816
|
+
flex-direction: column;
|
|
817
|
+
}
|
|
818
|
+
.vx-menu-item {
|
|
819
|
+
flex-direction: row;
|
|
820
|
+
align-items: center;
|
|
821
|
+
padding: 6px 10px;
|
|
822
|
+
border-radius: var(--radius-sm);
|
|
823
|
+
}
|
|
824
|
+
.vx-menu-item--disabled {
|
|
825
|
+
opacity: 0.5;
|
|
826
|
+
}
|
|
827
|
+
/* xplat-web-only:start — hover affordance and cursor are DOM-only */
|
|
828
|
+
.vx-menu-item {
|
|
829
|
+
cursor: pointer;
|
|
830
|
+
}
|
|
831
|
+
.vx-menu-item:hover {
|
|
832
|
+
background-color: var(--color-border);
|
|
833
|
+
}
|
|
834
|
+
/* xplat-web-only:end */
|
|
835
|
+
|
|
836
|
+
/* Badge — inline chip row. */
|
|
837
|
+
.vx-badge {
|
|
838
|
+
flex-direction: row;
|
|
839
|
+
align-items: center;
|
|
840
|
+
border-radius: var(--radius-sm);
|
|
841
|
+
padding: 1px 6px;
|
|
842
|
+
font-size: 12px;
|
|
843
|
+
line-height: 16px;
|
|
844
|
+
}
|
|
845
|
+
/* xplat-web-only:start — span is inline by default; needs inline-flex */
|
|
846
|
+
.vx-badge {
|
|
847
|
+
display: inline-flex;
|
|
848
|
+
}
|
|
849
|
+
/* xplat-web-only:end */
|
|
850
|
+
|
|
851
|
+
/* Separator — hairline rule; --h spans width, --v spans height. */
|
|
852
|
+
.vx-separator--h {
|
|
853
|
+
height: 1px;
|
|
854
|
+
background-color: var(--color-border);
|
|
855
|
+
}
|
|
856
|
+
.vx-separator--v {
|
|
857
|
+
width: 1px;
|
|
858
|
+
align-self: stretch;
|
|
859
|
+
background-color: var(--color-border);
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
/* Skeleton — placeholder block. */
|
|
863
|
+
.vx-skeleton {
|
|
864
|
+
background-color: var(--color-border);
|
|
865
|
+
border-radius: var(--radius-md);
|
|
866
|
+
corner-shape: squircle;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
/* Avatar — centered fallback inside the circle. */
|
|
870
|
+
.vx-avatar {
|
|
871
|
+
align-items: center;
|
|
872
|
+
justify-content: center;
|
|
873
|
+
background-color: var(--color-border);
|
|
874
|
+
}
|
|
875
|
+
.vx-avatar-group {
|
|
876
|
+
flex-direction: row;
|
|
877
|
+
align-items: center;
|
|
878
|
+
}
|
|
879
|
+
/* xplat-web-only:start — display:flex for the div-based flex classes */
|
|
880
|
+
.vx-collapsible,
|
|
881
|
+
.vx-collapsible-content,
|
|
882
|
+
.vx-accordion,
|
|
883
|
+
.vx-accordion-item,
|
|
884
|
+
.vx-checkbox-row,
|
|
885
|
+
.vx-checkbox,
|
|
886
|
+
.vx-radio-group,
|
|
887
|
+
.vx-radio-row,
|
|
888
|
+
.vx-radio,
|
|
889
|
+
.vx-menu-list,
|
|
890
|
+
.vx-menu-item,
|
|
891
|
+
.vx-contextmenu,
|
|
892
|
+
.vx-avatar,
|
|
893
|
+
.vx-avatar-group,
|
|
894
|
+
.vx-avatar-group-item {
|
|
895
|
+
display: flex;
|
|
896
|
+
}
|
|
897
|
+
.vx-checkbox-row,
|
|
898
|
+
.vx-radio-row {
|
|
899
|
+
cursor: pointer;
|
|
900
|
+
}
|
|
901
|
+
.vx-checkbox-check {
|
|
902
|
+
display: block;
|
|
903
|
+
}
|
|
904
|
+
/* xplat-web-only:end */
|
|
905
|
+
|
|
906
|
+
/* Phase-2 form field layer. */
|
|
907
|
+
|
|
908
|
+
/* FormField — label / control / message column. */
|
|
909
|
+
.vx-field {
|
|
910
|
+
flex-direction: column;
|
|
911
|
+
}
|
|
912
|
+
.vx-field-label {
|
|
913
|
+
font-size: 13px;
|
|
914
|
+
line-height: 20px;
|
|
915
|
+
font-weight: 500;
|
|
916
|
+
margin-bottom: 4px;
|
|
917
|
+
}
|
|
918
|
+
.vx-field-required {
|
|
919
|
+
color: var(--color-danger);
|
|
920
|
+
}
|
|
921
|
+
.vx-field-msg {
|
|
922
|
+
font-size: 12px;
|
|
923
|
+
line-height: 16px;
|
|
924
|
+
margin-top: 4px;
|
|
925
|
+
color: var(--color-text-secondary);
|
|
926
|
+
}
|
|
927
|
+
.vx-field-msg--error {
|
|
928
|
+
color: var(--color-danger);
|
|
929
|
+
}
|
|
930
|
+
.vx-fieldgroup {
|
|
931
|
+
flex-direction: column;
|
|
932
|
+
}
|
|
933
|
+
.vx-fieldgroup-label {
|
|
934
|
+
font-size: 13px;
|
|
935
|
+
line-height: 20px;
|
|
936
|
+
font-weight: 600;
|
|
937
|
+
margin-bottom: 8px;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
/* InputNumber — steppers flanking a centered field. */
|
|
941
|
+
.vx-inputnumber {
|
|
942
|
+
flex-direction: row;
|
|
943
|
+
align-items: center;
|
|
944
|
+
}
|
|
945
|
+
.vx-inputnumber-step {
|
|
946
|
+
padding: 4px 10px;
|
|
947
|
+
border-width: 1px;
|
|
948
|
+
border-color: var(--color-border);
|
|
949
|
+
border-radius: var(--radius-sm);
|
|
950
|
+
align-items: center;
|
|
951
|
+
justify-content: center;
|
|
952
|
+
}
|
|
953
|
+
.vx-inputnumber-field {
|
|
954
|
+
width: 64px;
|
|
955
|
+
margin-left: 8px;
|
|
956
|
+
margin-right: 8px;
|
|
957
|
+
text-align: center;
|
|
958
|
+
}
|
|
959
|
+
.vx-inputnumber--disabled {
|
|
960
|
+
opacity: 0.5;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
/* PinInput — row of single cells. */
|
|
964
|
+
.vx-pininput {
|
|
965
|
+
flex-direction: row;
|
|
966
|
+
}
|
|
967
|
+
.vx-pininput-cell {
|
|
968
|
+
width: 40px;
|
|
969
|
+
margin-right: 8px;
|
|
970
|
+
text-align: center;
|
|
971
|
+
}
|
|
972
|
+
.vx-pininput--disabled {
|
|
973
|
+
opacity: 0.5;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
/* Select — trigger row + check column inside the anchored listbox. */
|
|
977
|
+
.vx-select-trigger {
|
|
978
|
+
flex-direction: row;
|
|
979
|
+
align-items: center;
|
|
980
|
+
justify-content: space-between;
|
|
981
|
+
padding: 6px 10px;
|
|
982
|
+
border-width: 1px;
|
|
983
|
+
border-color: var(--color-border);
|
|
984
|
+
border-radius: var(--radius-sm);
|
|
985
|
+
}
|
|
986
|
+
.vx-select--disabled {
|
|
987
|
+
opacity: 0.5;
|
|
988
|
+
}
|
|
989
|
+
.vx-select-placeholder {
|
|
990
|
+
color: var(--color-text-secondary);
|
|
991
|
+
}
|
|
992
|
+
.vx-select-caret {
|
|
993
|
+
margin-left: 8px;
|
|
994
|
+
}
|
|
995
|
+
.vx-select-check {
|
|
996
|
+
width: 16px;
|
|
997
|
+
}
|
|
998
|
+
.vx-select-search {
|
|
999
|
+
margin-bottom: 4px;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
/* InputTags — wrapped chip row + trailing field. */
|
|
1003
|
+
.vx-inputtags {
|
|
1004
|
+
flex-direction: row;
|
|
1005
|
+
flex-wrap: wrap;
|
|
1006
|
+
align-items: center;
|
|
1007
|
+
}
|
|
1008
|
+
.vx-inputtags-tag {
|
|
1009
|
+
flex-direction: row;
|
|
1010
|
+
align-items: center;
|
|
1011
|
+
padding: 1px 6px;
|
|
1012
|
+
margin-right: 4px;
|
|
1013
|
+
margin-bottom: 4px;
|
|
1014
|
+
border-radius: var(--radius-sm);
|
|
1015
|
+
background-color: var(--color-border);
|
|
1016
|
+
}
|
|
1017
|
+
.vx-inputtags-remove {
|
|
1018
|
+
margin-left: 4px;
|
|
1019
|
+
}
|
|
1020
|
+
.vx-inputtags-field {
|
|
1021
|
+
flex: 1;
|
|
1022
|
+
min-width: 80px;
|
|
1023
|
+
}
|
|
1024
|
+
.vx-inputtags--disabled {
|
|
1025
|
+
opacity: 0.5;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
/* InputRating — glyph row; --on lights the cell. */
|
|
1029
|
+
.vx-rating {
|
|
1030
|
+
flex-direction: row;
|
|
1031
|
+
}
|
|
1032
|
+
.vx-rating-cell {
|
|
1033
|
+
padding: 2px;
|
|
1034
|
+
}
|
|
1035
|
+
.vx-rating-glyph {
|
|
1036
|
+
font-size: 20px;
|
|
1037
|
+
line-height: 24px;
|
|
1038
|
+
color: var(--color-border);
|
|
1039
|
+
}
|
|
1040
|
+
.vx-rating-cell--on .vx-rating-glyph {
|
|
1041
|
+
color: var(--color-primary);
|
|
1042
|
+
}
|
|
1043
|
+
.vx-rating--disabled {
|
|
1044
|
+
opacity: 0.5;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
/* CheckboxGroup — column/row of checkboxes. */
|
|
1048
|
+
.vx-checkbox-group {
|
|
1049
|
+
flex-direction: column;
|
|
1050
|
+
}
|
|
1051
|
+
.vx-checkbox-group--row {
|
|
1052
|
+
flex-direction: row;
|
|
1053
|
+
}
|
|
1054
|
+
/* xplat-web-only:start — display:flex for the div/span flex classes */
|
|
1055
|
+
.vx-field,
|
|
1056
|
+
.vx-fieldgroup,
|
|
1057
|
+
.vx-inputnumber,
|
|
1058
|
+
.vx-inputnumber-step,
|
|
1059
|
+
.vx-select-trigger,
|
|
1060
|
+
.vx-select-list,
|
|
1061
|
+
.vx-inputtags,
|
|
1062
|
+
.vx-inputtags-tag,
|
|
1063
|
+
.vx-rating,
|
|
1064
|
+
.vx-rating-cell,
|
|
1065
|
+
.vx-checkbox-group {
|
|
1066
|
+
display: flex;
|
|
1067
|
+
}
|
|
1068
|
+
.vx-rating-cell {
|
|
1069
|
+
cursor: pointer;
|
|
1070
|
+
}
|
|
1071
|
+
/* xplat-web-only:end */
|
|
1072
|
+
|
|
1073
|
+
/* Phase-3 navigation & wayfinding. */
|
|
1074
|
+
|
|
1075
|
+
/* Breadcrumb — inline trail. */
|
|
1076
|
+
.vx-breadcrumb {
|
|
1077
|
+
flex-direction: row;
|
|
1078
|
+
align-items: center;
|
|
1079
|
+
flex-wrap: wrap;
|
|
1080
|
+
}
|
|
1081
|
+
.vx-breadcrumb-item {
|
|
1082
|
+
flex-direction: row;
|
|
1083
|
+
align-items: center;
|
|
1084
|
+
}
|
|
1085
|
+
.vx-breadcrumb-sep {
|
|
1086
|
+
margin-left: 6px;
|
|
1087
|
+
margin-right: 6px;
|
|
1088
|
+
color: var(--color-text-secondary);
|
|
1089
|
+
}
|
|
1090
|
+
.vx-breadcrumb-link {
|
|
1091
|
+
color: var(--color-primary);
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
/* Pagination — windowed page buttons. */
|
|
1095
|
+
.vx-pagination {
|
|
1096
|
+
flex-direction: row;
|
|
1097
|
+
align-items: center;
|
|
1098
|
+
}
|
|
1099
|
+
.vx-page-btn {
|
|
1100
|
+
min-width: 28px;
|
|
1101
|
+
height: 28px;
|
|
1102
|
+
padding: 0 6px;
|
|
1103
|
+
margin-right: 4px;
|
|
1104
|
+
border-width: 1px;
|
|
1105
|
+
border-color: var(--color-border);
|
|
1106
|
+
border-radius: var(--radius-sm);
|
|
1107
|
+
align-items: center;
|
|
1108
|
+
justify-content: center;
|
|
1109
|
+
}
|
|
1110
|
+
.vx-page-btn--on {
|
|
1111
|
+
background-color: var(--color-primary);
|
|
1112
|
+
border-color: var(--color-primary);
|
|
1113
|
+
color: var(--color-onprimary);
|
|
1114
|
+
}
|
|
1115
|
+
.vx-page-ellipsis {
|
|
1116
|
+
margin-right: 4px;
|
|
1117
|
+
color: var(--color-text-secondary);
|
|
1118
|
+
}
|
|
1119
|
+
.vx-pagination--disabled {
|
|
1120
|
+
opacity: 0.5;
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
/* Stepper — dot + label cells joined by a hairline. */
|
|
1124
|
+
.vx-stepper {
|
|
1125
|
+
flex-direction: row;
|
|
1126
|
+
align-items: center;
|
|
1127
|
+
}
|
|
1128
|
+
.vx-stepper-cell {
|
|
1129
|
+
flex-direction: row;
|
|
1130
|
+
align-items: center;
|
|
1131
|
+
}
|
|
1132
|
+
.vx-stepper-line {
|
|
1133
|
+
width: 24px;
|
|
1134
|
+
height: 1px;
|
|
1135
|
+
background-color: var(--color-border);
|
|
1136
|
+
}
|
|
1137
|
+
.vx-stepper-line--done {
|
|
1138
|
+
background-color: var(--color-primary);
|
|
1139
|
+
}
|
|
1140
|
+
.vx-step {
|
|
1141
|
+
flex-direction: row;
|
|
1142
|
+
align-items: center;
|
|
1143
|
+
}
|
|
1144
|
+
.vx-step-dot {
|
|
1145
|
+
width: 24px;
|
|
1146
|
+
height: 24px;
|
|
1147
|
+
border-width: 1px;
|
|
1148
|
+
border-color: var(--color-border);
|
|
1149
|
+
border-radius: 50%;
|
|
1150
|
+
text-align: center;
|
|
1151
|
+
font-size: 12px;
|
|
1152
|
+
line-height: 22px;
|
|
1153
|
+
color: var(--color-text-secondary);
|
|
1154
|
+
}
|
|
1155
|
+
.vx-step--on .vx-step-dot {
|
|
1156
|
+
border-color: var(--color-primary);
|
|
1157
|
+
color: var(--color-primary);
|
|
1158
|
+
}
|
|
1159
|
+
.vx-step--done .vx-step-dot {
|
|
1160
|
+
background-color: var(--color-primary);
|
|
1161
|
+
border-color: var(--color-primary);
|
|
1162
|
+
color: var(--color-onprimary);
|
|
1163
|
+
}
|
|
1164
|
+
.vx-step-label {
|
|
1165
|
+
margin-left: 6px;
|
|
1166
|
+
}
|
|
1167
|
+
.vx-step--disabled {
|
|
1168
|
+
opacity: 0.5;
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
/* NavigationMenu — row/column of nav items. */
|
|
1172
|
+
.vx-navmenu,
|
|
1173
|
+
.vx-navmenu--row {
|
|
1174
|
+
flex-direction: row;
|
|
1175
|
+
align-items: center;
|
|
1176
|
+
}
|
|
1177
|
+
.vx-navmenu--col {
|
|
1178
|
+
flex-direction: column;
|
|
1179
|
+
align-items: flex-start;
|
|
1180
|
+
}
|
|
1181
|
+
.vx-navmenu-item {
|
|
1182
|
+
flex-direction: row;
|
|
1183
|
+
align-items: center;
|
|
1184
|
+
padding: 6px 10px;
|
|
1185
|
+
border-radius: var(--radius-sm);
|
|
1186
|
+
}
|
|
1187
|
+
.vx-navmenu-item--on {
|
|
1188
|
+
background-color: var(--color-border);
|
|
1189
|
+
}
|
|
1190
|
+
.vx-navmenu-item--disabled {
|
|
1191
|
+
opacity: 0.5;
|
|
1192
|
+
}
|
|
1193
|
+
.vx-navmenu-label {
|
|
1194
|
+
margin-left: 4px;
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
/* CommandPalette — panel centered by the overlay layer. */
|
|
1198
|
+
.vx-commandpalette {
|
|
1199
|
+
width: 360px;
|
|
1200
|
+
max-width: 90%;
|
|
1201
|
+
padding: 8px;
|
|
1202
|
+
border-width: 1px;
|
|
1203
|
+
border-color: var(--color-border);
|
|
1204
|
+
border-radius: var(--radius-md);
|
|
1205
|
+
corner-shape: squircle;
|
|
1206
|
+
background-color: var(--color-surface);
|
|
1207
|
+
color: var(--color-text);
|
|
1208
|
+
}
|
|
1209
|
+
.vx-cmdk-search {
|
|
1210
|
+
margin-bottom: 4px;
|
|
1211
|
+
}
|
|
1212
|
+
/* xplat-web-only:start — display, centering, and cursor are DOM-only */
|
|
1213
|
+
.vx-breadcrumb,
|
|
1214
|
+
.vx-breadcrumb-item,
|
|
1215
|
+
.vx-pagination,
|
|
1216
|
+
.vx-page-btn,
|
|
1217
|
+
.vx-stepper,
|
|
1218
|
+
.vx-stepper-cell,
|
|
1219
|
+
.vx-step,
|
|
1220
|
+
.vx-navmenu,
|
|
1221
|
+
.vx-navmenu-item {
|
|
1222
|
+
display: flex;
|
|
1223
|
+
}
|
|
1224
|
+
.vx-cmdk-layer .vx-overlay-content {
|
|
1225
|
+
position: absolute;
|
|
1226
|
+
top: 15%;
|
|
1227
|
+
left: 50%;
|
|
1228
|
+
transform: translateX(-50%);
|
|
1229
|
+
}
|
|
1230
|
+
.vx-page-btn,
|
|
1231
|
+
.vx-breadcrumb-link,
|
|
1232
|
+
.vx-step,
|
|
1233
|
+
.vx-navmenu-item {
|
|
1234
|
+
cursor: pointer;
|
|
1235
|
+
}
|
|
1236
|
+
/* xplat-web-only:end */
|
|
1237
|
+
|
|
1238
|
+
/* Phase-4 data display. */
|
|
1239
|
+
|
|
1240
|
+
/* Table — header + bounded rows (unvirtualized by design). */
|
|
1241
|
+
.vx-table {
|
|
1242
|
+
flex-direction: column;
|
|
1243
|
+
border-width: 1px;
|
|
1244
|
+
border-color: var(--color-border);
|
|
1245
|
+
border-radius: var(--radius-md);
|
|
1246
|
+
}
|
|
1247
|
+
.vx-table-head,
|
|
1248
|
+
.vx-table-row {
|
|
1249
|
+
flex-direction: row;
|
|
1250
|
+
}
|
|
1251
|
+
.vx-table-th {
|
|
1252
|
+
font-weight: 600;
|
|
1253
|
+
}
|
|
1254
|
+
.vx-table-cell {
|
|
1255
|
+
padding: 8px 12px;
|
|
1256
|
+
}
|
|
1257
|
+
.vx-table-head {
|
|
1258
|
+
border-bottom-width: 1px;
|
|
1259
|
+
border-bottom-color: var(--color-border);
|
|
1260
|
+
}
|
|
1261
|
+
.vx-table-empty {
|
|
1262
|
+
padding: 16px;
|
|
1263
|
+
align-items: center;
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
/* Timeline — dot + connector rail beside content. */
|
|
1267
|
+
.vx-timeline {
|
|
1268
|
+
flex-direction: column;
|
|
1269
|
+
}
|
|
1270
|
+
.vx-timeline-item {
|
|
1271
|
+
flex-direction: row;
|
|
1272
|
+
}
|
|
1273
|
+
.vx-timeline-rail {
|
|
1274
|
+
flex-direction: column;
|
|
1275
|
+
align-items: center;
|
|
1276
|
+
width: 20px;
|
|
1277
|
+
}
|
|
1278
|
+
.vx-timeline-dot {
|
|
1279
|
+
width: 10px;
|
|
1280
|
+
height: 10px;
|
|
1281
|
+
margin-top: 5px;
|
|
1282
|
+
border-radius: 50%;
|
|
1283
|
+
background-color: var(--color-primary);
|
|
1284
|
+
align-items: center;
|
|
1285
|
+
justify-content: center;
|
|
1286
|
+
}
|
|
1287
|
+
.vx-timeline-line {
|
|
1288
|
+
width: 1px;
|
|
1289
|
+
flex: 1;
|
|
1290
|
+
background-color: var(--color-border);
|
|
1291
|
+
}
|
|
1292
|
+
.vx-timeline-body {
|
|
1293
|
+
flex-direction: column;
|
|
1294
|
+
padding-left: 10px;
|
|
1295
|
+
padding-bottom: 16px;
|
|
1296
|
+
}
|
|
1297
|
+
.vx-timeline-time {
|
|
1298
|
+
font-size: 12px;
|
|
1299
|
+
line-height: 16px;
|
|
1300
|
+
color: var(--color-text-secondary);
|
|
1301
|
+
}
|
|
1302
|
+
.vx-timeline-title {
|
|
1303
|
+
font-weight: 600;
|
|
1304
|
+
}
|
|
1305
|
+
.vx-timeline-desc {
|
|
1306
|
+
color: var(--color-text-secondary);
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
/* Tree — indented collapsible rows. */
|
|
1310
|
+
.vx-tree {
|
|
1311
|
+
flex-direction: column;
|
|
1312
|
+
}
|
|
1313
|
+
.vx-tree-node {
|
|
1314
|
+
flex-direction: column;
|
|
1315
|
+
}
|
|
1316
|
+
.vx-tree-row {
|
|
1317
|
+
flex-direction: row;
|
|
1318
|
+
align-items: center;
|
|
1319
|
+
padding: 4px 0;
|
|
1320
|
+
}
|
|
1321
|
+
.vx-tree-row--disabled {
|
|
1322
|
+
opacity: 0.5;
|
|
1323
|
+
}
|
|
1324
|
+
.vx-tree-caret {
|
|
1325
|
+
width: 14px;
|
|
1326
|
+
margin-left: 4px;
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
/* Alert — icon + body callout; tone picks border/text colors. */
|
|
1330
|
+
.vx-alert {
|
|
1331
|
+
flex-direction: row;
|
|
1332
|
+
padding: 10px 12px;
|
|
1333
|
+
border-width: 1px;
|
|
1334
|
+
border-radius: var(--radius-md);
|
|
1335
|
+
corner-shape: squircle;
|
|
1336
|
+
border-color: var(--color-border);
|
|
1337
|
+
}
|
|
1338
|
+
.vx-alert-body {
|
|
1339
|
+
flex-direction: column;
|
|
1340
|
+
flex: 1;
|
|
1341
|
+
margin-left: 8px;
|
|
1342
|
+
}
|
|
1343
|
+
.vx-alert-title {
|
|
1344
|
+
font-weight: 600;
|
|
1345
|
+
}
|
|
1346
|
+
.vx-alert--error {
|
|
1347
|
+
border-color: var(--color-danger);
|
|
1348
|
+
}
|
|
1349
|
+
.vx-alert--warning {
|
|
1350
|
+
border-color: var(--color-warning, #d9a400);
|
|
1351
|
+
}
|
|
1352
|
+
.vx-alert--success {
|
|
1353
|
+
border-color: var(--color-success, #2e9e5b);
|
|
1354
|
+
}
|
|
1355
|
+
.vx-alert--info {
|
|
1356
|
+
border-color: var(--color-primary);
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
/* Card — sectioned container. */
|
|
1360
|
+
.vx-card {
|
|
1361
|
+
flex-direction: column;
|
|
1362
|
+
border-width: 1px;
|
|
1363
|
+
border-color: var(--color-border);
|
|
1364
|
+
border-radius: var(--radius-md);
|
|
1365
|
+
corner-shape: squircle;
|
|
1366
|
+
background-color: var(--color-surface);
|
|
1367
|
+
}
|
|
1368
|
+
.vx-card-header {
|
|
1369
|
+
padding: 12px;
|
|
1370
|
+
border-bottom-width: 1px;
|
|
1371
|
+
border-bottom-color: var(--color-border);
|
|
1372
|
+
}
|
|
1373
|
+
.vx-card-body {
|
|
1374
|
+
padding: 12px;
|
|
1375
|
+
flex-direction: column;
|
|
1376
|
+
}
|
|
1377
|
+
.vx-card-footer {
|
|
1378
|
+
padding: 12px;
|
|
1379
|
+
border-top-width: 1px;
|
|
1380
|
+
border-top-color: var(--color-border);
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
/* Chip — pressable pill with selected + remove states. */
|
|
1384
|
+
.vx-chip {
|
|
1385
|
+
flex-direction: row;
|
|
1386
|
+
align-items: center;
|
|
1387
|
+
padding: 3px 10px;
|
|
1388
|
+
border-width: 1px;
|
|
1389
|
+
border-color: var(--color-border);
|
|
1390
|
+
border-radius: var(--radius-md);
|
|
1391
|
+
corner-shape: squircle;
|
|
1392
|
+
font-size: 13px;
|
|
1393
|
+
}
|
|
1394
|
+
.vx-chip--on {
|
|
1395
|
+
background-color: var(--color-primary);
|
|
1396
|
+
border-color: var(--color-primary);
|
|
1397
|
+
color: var(--color-onprimary);
|
|
1398
|
+
}
|
|
1399
|
+
.vx-chip--disabled {
|
|
1400
|
+
opacity: 0.5;
|
|
1401
|
+
}
|
|
1402
|
+
.vx-chip-remove {
|
|
1403
|
+
margin-left: 6px;
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
/* Kbd — keycap glyph. */
|
|
1407
|
+
.vx-kbd {
|
|
1408
|
+
padding: 1px 5px;
|
|
1409
|
+
border-width: 1px;
|
|
1410
|
+
border-color: var(--color-border);
|
|
1411
|
+
border-bottom-width: 2px;
|
|
1412
|
+
border-radius: var(--radius-sm);
|
|
1413
|
+
font-size: 12px;
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
/* Empty — centered placeholder. */
|
|
1417
|
+
.vx-empty {
|
|
1418
|
+
flex-direction: column;
|
|
1419
|
+
align-items: center;
|
|
1420
|
+
padding: 24px;
|
|
1421
|
+
}
|
|
1422
|
+
.vx-empty-title {
|
|
1423
|
+
font-weight: 600;
|
|
1424
|
+
margin-top: 8px;
|
|
1425
|
+
}
|
|
1426
|
+
.vx-empty-desc {
|
|
1427
|
+
color: var(--color-text-secondary);
|
|
1428
|
+
margin-top: 2px;
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
/* Banner — notice strip. */
|
|
1432
|
+
.vx-banner {
|
|
1433
|
+
flex-direction: row;
|
|
1434
|
+
align-items: center;
|
|
1435
|
+
padding: 8px 12px;
|
|
1436
|
+
border-width: 1px;
|
|
1437
|
+
border-color: var(--color-border);
|
|
1438
|
+
border-radius: var(--radius-md);
|
|
1439
|
+
background-color: var(--color-surface);
|
|
1440
|
+
}
|
|
1441
|
+
.vx-banner-body {
|
|
1442
|
+
flex-direction: column;
|
|
1443
|
+
flex: 1;
|
|
1444
|
+
margin-left: 8px;
|
|
1445
|
+
}
|
|
1446
|
+
.vx-banner-dismiss {
|
|
1447
|
+
margin-left: 8px;
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
/* User — avatar + text column. */
|
|
1451
|
+
.vx-user {
|
|
1452
|
+
flex-direction: row;
|
|
1453
|
+
align-items: center;
|
|
1454
|
+
}
|
|
1455
|
+
.vx-user-body {
|
|
1456
|
+
flex-direction: column;
|
|
1457
|
+
margin-left: 10px;
|
|
1458
|
+
}
|
|
1459
|
+
.vx-user-name {
|
|
1460
|
+
font-weight: 600;
|
|
1461
|
+
}
|
|
1462
|
+
.vx-user-desc {
|
|
1463
|
+
font-size: 12px;
|
|
1464
|
+
line-height: 16px;
|
|
1465
|
+
color: var(--color-text-secondary);
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
/* ProgressGroup — stacked labeled meters. */
|
|
1469
|
+
.vx-progressgroup {
|
|
1470
|
+
flex-direction: column;
|
|
1471
|
+
}
|
|
1472
|
+
.vx-progressgroup-row {
|
|
1473
|
+
flex-direction: row;
|
|
1474
|
+
align-items: center;
|
|
1475
|
+
}
|
|
1476
|
+
.vx-progressgroup-label {
|
|
1477
|
+
margin-left: 8px;
|
|
1478
|
+
}
|
|
1479
|
+
/* xplat-web-only:start — display:flex for the div-based flex classes */
|
|
1480
|
+
.vx-table,
|
|
1481
|
+
.vx-table-head,
|
|
1482
|
+
.vx-table-row,
|
|
1483
|
+
.vx-timeline,
|
|
1484
|
+
.vx-timeline-item,
|
|
1485
|
+
.vx-timeline-rail,
|
|
1486
|
+
.vx-timeline-body,
|
|
1487
|
+
.vx-tree,
|
|
1488
|
+
.vx-tree-node,
|
|
1489
|
+
.vx-tree-row,
|
|
1490
|
+
.vx-alert,
|
|
1491
|
+
.vx-alert-body,
|
|
1492
|
+
.vx-card,
|
|
1493
|
+
.vx-card-body,
|
|
1494
|
+
.vx-banner,
|
|
1495
|
+
.vx-banner-body,
|
|
1496
|
+
.vx-user,
|
|
1497
|
+
.vx-user-body,
|
|
1498
|
+
.vx-progressgroup,
|
|
1499
|
+
.vx-progressgroup-row {
|
|
1500
|
+
display: flex;
|
|
1501
|
+
}
|
|
1502
|
+
.vx-table-row--pressable,
|
|
1503
|
+
.vx-tree-row,
|
|
1504
|
+
.vx-user--pressable,
|
|
1505
|
+
.vx-banner-dismiss,
|
|
1506
|
+
.vx-chip-remove {
|
|
1507
|
+
cursor: pointer;
|
|
1508
|
+
}
|
|
1509
|
+
/* xplat-web-only:end */
|
|
1510
|
+
|
|
1511
|
+
.vx-h1 {
|
|
1512
|
+
font-size: 2em;
|
|
1513
|
+
font-weight: bold;
|
|
1514
|
+
}
|
|
1515
|
+
.vx-h2 {
|
|
1516
|
+
font-size: 1.5em;
|
|
1517
|
+
font-weight: bold;
|
|
1518
|
+
}
|
|
1519
|
+
.vx-h3 {
|
|
1520
|
+
font-size: 1.17em;
|
|
1521
|
+
font-weight: bold;
|
|
1522
|
+
}
|
|
1523
|
+
.vx-h4 {
|
|
1524
|
+
font-size: 1em;
|
|
1525
|
+
font-weight: bold;
|
|
1526
|
+
}
|
|
1527
|
+
.vx-h5 {
|
|
1528
|
+
font-size: 0.83em;
|
|
1529
|
+
font-weight: bold;
|
|
1530
|
+
}
|
|
1531
|
+
.vx-h6 {
|
|
1532
|
+
font-size: 0.67em;
|
|
1533
|
+
font-weight: bold;
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
/* utilities (hand-written subset — do NOT adopt Tailwind until
|
|
1537
|
+
NativeScript/tailwind#226 is resolved; the plugin strips core-supported
|
|
1538
|
+
props incl. gap, drops all @media, and rewrites invisible→collapse) */
|
|
1539
|
+
|
|
1540
|
+
/* flex-1 keeps Tailwind v4's exact emission (`flex: 1 1 0%`) — web gets
|
|
1541
|
+
identical semantics, NS parses grow/shrink out of the shorthand and
|
|
1542
|
+
ignores the basis token it can't model. */
|
|
1543
|
+
.flex-1 {
|
|
1544
|
+
flex: 1 1 0%;
|
|
1545
|
+
}
|
|
1546
|
+
/* Flex divergence guards — NS FlexboxLayout diverges from web flexbox on
|
|
1547
|
+
* shrinkability: grow children never shrink below intrinsic width, fixed
|
|
1548
|
+
* children get crushed, and auto-height rows re-measure grow children at
|
|
1549
|
+
* zero height. The shared `* { flex-shrink: 0 }` default (RN semantics)
|
|
1550
|
+
* makes .shrink the opt-in for a shrinkable child; min-w-0/min-h-0 lower
|
|
1551
|
+
* the min-content floor so it can actually shrink, and shrink-0 remains
|
|
1552
|
+
* for local overrides. All four are plain CSS on web. */
|
|
1553
|
+
.min-w-0 {
|
|
1554
|
+
min-width: 0;
|
|
1555
|
+
}
|
|
1556
|
+
.min-h-0 {
|
|
1557
|
+
min-height: 0;
|
|
1558
|
+
}
|
|
1559
|
+
.shrink {
|
|
1560
|
+
flex-shrink: 1;
|
|
1561
|
+
}
|
|
1562
|
+
.shrink-0 {
|
|
1563
|
+
flex-shrink: 0;
|
|
1564
|
+
}
|
|
1565
|
+
.grow {
|
|
1566
|
+
flex-grow: 1;
|
|
1567
|
+
}
|
|
1568
|
+
.items-center {
|
|
1569
|
+
align-items: center;
|
|
1570
|
+
}
|
|
1571
|
+
.items-baseline {
|
|
1572
|
+
align-items: baseline;
|
|
1573
|
+
}
|
|
1574
|
+
.items-start {
|
|
1575
|
+
align-items: flex-start;
|
|
1576
|
+
}
|
|
1577
|
+
.justify-center {
|
|
1578
|
+
justify-content: center;
|
|
1579
|
+
}
|
|
1580
|
+
.justify-between {
|
|
1581
|
+
justify-content: space-between;
|
|
1582
|
+
}
|
|
1583
|
+
.flex-wrap {
|
|
1584
|
+
flex-wrap: wrap;
|
|
1585
|
+
}
|
|
1586
|
+
.gap-4 {
|
|
1587
|
+
gap: 16px;
|
|
1588
|
+
}
|
|
1589
|
+
.gap-3 {
|
|
1590
|
+
gap: 12px;
|
|
1591
|
+
}
|
|
1592
|
+
.gap-6 {
|
|
1593
|
+
gap: 24px;
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
/* line-height is REQUIRED on native: without it a Label's measured height
|
|
1597
|
+
misses the font's line metrics, and Android clips the descenders/bottom
|
|
1598
|
+
of the glyphs (observed: section-labels 21–29px bounds for 12sp text at
|
|
1599
|
+
3.25x). Tailwind pairs every text-* size with a leading, same here. */
|
|
1600
|
+
.text-2xl {
|
|
1601
|
+
font-size: 28px;
|
|
1602
|
+
line-height: 36px;
|
|
1603
|
+
}
|
|
1604
|
+
.text-xl {
|
|
1605
|
+
font-size: 20px;
|
|
1606
|
+
line-height: 28px;
|
|
1607
|
+
}
|
|
1608
|
+
.text-lg {
|
|
1609
|
+
font-size: 18px;
|
|
1610
|
+
line-height: 28px;
|
|
1611
|
+
}
|
|
1612
|
+
.text-sm {
|
|
1613
|
+
font-size: 13px;
|
|
1614
|
+
line-height: 20px;
|
|
1615
|
+
}
|
|
1616
|
+
.font-bold {
|
|
1617
|
+
font-weight: bold;
|
|
1618
|
+
}
|
|
1619
|
+
.font-semibold {
|
|
1620
|
+
font-weight: 600;
|
|
1621
|
+
}
|
|
1622
|
+
.text-muted {
|
|
1623
|
+
color: var(--color-text-secondary);
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
/* Corner utilities — consume the --radius-* scale and carry the smooth
|
|
1627
|
+
(squircle) corner treatment. Circles stay circular: .rounded-full omits
|
|
1628
|
+
corner-shape deliberately (squircle at full radius = a squircle disk,
|
|
1629
|
+
not a circle). Opt out per element with `corner-shape: round`. */
|
|
1630
|
+
.rounded-sm {
|
|
1631
|
+
border-radius: var(--radius-sm);
|
|
1632
|
+
corner-shape: squircle;
|
|
1633
|
+
}
|
|
1634
|
+
.rounded-md {
|
|
1635
|
+
border-radius: var(--radius-md);
|
|
1636
|
+
corner-shape: squircle;
|
|
1637
|
+
}
|
|
1638
|
+
.rounded-lg {
|
|
1639
|
+
border-radius: var(--radius-lg);
|
|
1640
|
+
corner-shape: squircle;
|
|
1641
|
+
}
|
|
1642
|
+
.rounded-xl {
|
|
1643
|
+
border-radius: var(--radius-xl);
|
|
1644
|
+
corner-shape: squircle;
|
|
1645
|
+
}
|
|
1646
|
+
.rounded-full {
|
|
1647
|
+
border-radius: 9999px;
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
.bg-primary {
|
|
1651
|
+
background-color: var(--color-primary);
|
|
1652
|
+
}
|
|
1653
|
+
.text-onprimary {
|
|
1654
|
+
color: var(--color-onprimary);
|
|
1655
|
+
}
|
|
1656
|
+
.bg-danger {
|
|
1657
|
+
background-color: var(--color-danger);
|
|
1658
|
+
}
|
|
1659
|
+
/* xplat-web-only:start — box-shadow is inert on native (elevation is
|
|
1660
|
+
Android-only; no shared mapping yet) */
|
|
1661
|
+
.shadow-2 {
|
|
1662
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
|
|
1663
|
+
}
|
|
1664
|
+
/* xplat-web-only:end */
|
|
1665
|
+
|
|
1666
|
+
.btn {
|
|
1667
|
+
padding-top: 10px;
|
|
1668
|
+
padding-right: 16px;
|
|
1669
|
+
padding-bottom: 10px;
|
|
1670
|
+
padding-left: 16px;
|
|
1671
|
+
border-radius: var(--radius-md);
|
|
1672
|
+
corner-shape: squircle;
|
|
1673
|
+
font-size: 14px;
|
|
1674
|
+
font-weight: 500;
|
|
1675
|
+
align-items: center;
|
|
1676
|
+
justify-content: center;
|
|
1677
|
+
text-decoration: none;
|
|
1678
|
+
color: var(--color-text);
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
/* Secondary = the same control reading quiet: hairline border, surface
|
|
1682
|
+
fill, body-text label. Reserve .bg-primary for the one decisive action
|
|
1683
|
+
in a group. */
|
|
1684
|
+
.btn-secondary {
|
|
1685
|
+
background-color: var(--color-surface);
|
|
1686
|
+
border-width: 1px;
|
|
1687
|
+
border-color: var(--color-border);
|
|
1688
|
+
color: var(--color-text);
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
/* xplat-web-only:start — controls that render as real <a>/<button> need
|
|
1692
|
+
inline layout and UA resets; the pressable/nav-link leaves are divs on
|
|
1693
|
+
web and don't hit these rules. */
|
|
1694
|
+
a.btn {
|
|
1695
|
+
display: inline-flex;
|
|
1696
|
+
}
|
|
1697
|
+
a.chip {
|
|
1698
|
+
display: inline-flex;
|
|
1699
|
+
align-items: center;
|
|
1700
|
+
}
|
|
1701
|
+
/* xplat-web-only:end */
|
|
1702
|
+
|
|
1703
|
+
/* Tab shell — web divs/buttons + the Android SwapTabs fallback (iOS draws
|
|
1704
|
+
its own UITabBar and never sees these). */
|
|
1705
|
+
.vx-tabbar {
|
|
1706
|
+
border-bottom-width: 1px;
|
|
1707
|
+
border-bottom-color: var(--color-border);
|
|
1708
|
+
background-color: var(--color-surface);
|
|
1709
|
+
}
|
|
1710
|
+
.vx-tab {
|
|
1711
|
+
align-items: center;
|
|
1712
|
+
justify-content: center;
|
|
1713
|
+
padding-top: 10px;
|
|
1714
|
+
padding-right: 16px;
|
|
1715
|
+
padding-bottom: 10px;
|
|
1716
|
+
padding-left: 16px;
|
|
1717
|
+
font-size: 14px;
|
|
1718
|
+
color: var(--color-text-secondary);
|
|
1719
|
+
}
|
|
1720
|
+
.vx-tab.active {
|
|
1721
|
+
color: var(--color-text);
|
|
1722
|
+
}
|
|
1723
|
+
.vx-tabicon {
|
|
1724
|
+
margin-right: 6px;
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
/* xplat-web-only:start — DOM defaults are display:block (div) and
|
|
1728
|
+
inline-block (button); every flex-bearing vx- class needs an explicit
|
|
1729
|
+
display or flex-direction/align-items/justify-content are inert. */
|
|
1730
|
+
.vx-tabs {
|
|
1731
|
+
display: flex;
|
|
1732
|
+
flex-direction: column;
|
|
1733
|
+
flex: 1;
|
|
1734
|
+
min-height: 0;
|
|
1735
|
+
}
|
|
1736
|
+
.vx-tabbar {
|
|
1737
|
+
display: flex;
|
|
1738
|
+
flex-direction: row;
|
|
1739
|
+
}
|
|
1740
|
+
.vx-tabpane {
|
|
1741
|
+
flex: 1;
|
|
1742
|
+
min-height: 0;
|
|
1743
|
+
display: flex;
|
|
1744
|
+
flex-direction: column;
|
|
1745
|
+
}
|
|
1746
|
+
button.vx-tab {
|
|
1747
|
+
display: flex;
|
|
1748
|
+
background: none;
|
|
1749
|
+
cursor: pointer;
|
|
1750
|
+
}
|
|
1751
|
+
/* xplat-web-only:end */
|
|
1752
|
+
|
|
1753
|
+
/* harness experiment styles */
|
|
1754
|
+
|
|
1755
|
+
.vx-app {
|
|
1756
|
+
padding: 24px;
|
|
1757
|
+
background-color: var(--color-surface);
|
|
1758
|
+
color: var(--color-text);
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
.vx-app .text-xl,
|
|
1762
|
+
.vx-app Text,
|
|
1763
|
+
.vx-app label {
|
|
1764
|
+
color: var(--color-text);
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
/* `.vx-app label` above (descendant + type) outranks single-class text
|
|
1768
|
+
colors inside the app root — roles that must win escalate here. */
|
|
1769
|
+
.vx-app .text-onprimary {
|
|
1770
|
+
color: var(--color-onprimary);
|
|
1771
|
+
}
|
|
1772
|
+
.vx-app .text-muted {
|
|
1773
|
+
color: var(--color-text-secondary);
|
|
1774
|
+
}
|
|
1775
|
+
.vx-app .vx-tab label {
|
|
1776
|
+
color: var(--color-text-secondary);
|
|
1777
|
+
}
|
|
1778
|
+
.vx-app .vx-tab.active label {
|
|
1779
|
+
color: var(--color-text);
|
|
1780
|
+
}
|
|
1781
|
+
.vx-app .chip-on label {
|
|
1782
|
+
color: var(--color-onprimary);
|
|
1783
|
+
}
|
|
1784
|
+
/* Danger surfaces keep white text in both themes (on-primary flips). */
|
|
1785
|
+
.bg-danger .text-onprimary {
|
|
1786
|
+
color: #ffffff;
|
|
1787
|
+
}
|
|
1788
|
+
|
|
445
1789
|
.input {
|
|
446
|
-
padding: 10px;
|
|
1790
|
+
padding-top: 10px;
|
|
1791
|
+
padding-right: 12px;
|
|
1792
|
+
padding-bottom: 10px;
|
|
1793
|
+
padding-left: 12px;
|
|
447
1794
|
border-width: 1px;
|
|
448
|
-
border-color:
|
|
449
|
-
border-radius: var(--radius-
|
|
1795
|
+
border-color: var(--color-border);
|
|
1796
|
+
border-radius: var(--radius-md);
|
|
450
1797
|
corner-shape: squircle;
|
|
451
|
-
font-size:
|
|
1798
|
+
font-size: 14px;
|
|
1799
|
+
background-color: var(--color-surface);
|
|
1800
|
+
color: var(--color-text);
|
|
1801
|
+
/* NS TextField/TextView placeholder color (ignored on web — the
|
|
1802
|
+
::placeholder pseudo above covers it there). */
|
|
1803
|
+
placeholder-color: var(--color-text-secondary);
|
|
452
1804
|
}
|
|
453
1805
|
|
|
454
1806
|
.chip {
|
|
455
|
-
background-color: var(--color-
|
|
456
|
-
color: var(--color-
|
|
457
|
-
padding:
|
|
458
|
-
|
|
1807
|
+
background-color: var(--color-surface);
|
|
1808
|
+
color: var(--color-text);
|
|
1809
|
+
padding-top: 5px;
|
|
1810
|
+
padding-right: 12px;
|
|
1811
|
+
padding-bottom: 5px;
|
|
1812
|
+
padding-left: 12px;
|
|
1813
|
+
border-width: 1px;
|
|
1814
|
+
border-color: var(--color-border);
|
|
1815
|
+
border-radius: var(--radius-md);
|
|
459
1816
|
corner-shape: squircle;
|
|
460
1817
|
font-size: 13px;
|
|
1818
|
+
text-decoration: none;
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
/* Selected chip — the one filled element in a group of bordered peers. */
|
|
1822
|
+
.chip-on {
|
|
1823
|
+
background-color: var(--color-primary);
|
|
1824
|
+
border-color: var(--color-primary);
|
|
1825
|
+
color: var(--color-onprimary);
|
|
461
1826
|
}
|
|
462
1827
|
|
|
463
1828
|
.cell {
|
|
464
1829
|
padding: 12px;
|
|
465
1830
|
border-bottom-width: 1px;
|
|
466
|
-
border-bottom-color:
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
.vx-list {
|
|
470
|
-
flex-grow: 1;
|
|
1831
|
+
border-bottom-color: var(--color-border);
|
|
471
1832
|
}
|
|
472
1833
|
|
|
473
1834
|
.gap-2 {
|
|
@@ -477,31 +1838,75 @@ textarea::placeholder {
|
|
|
477
1838
|
/* In-window sheet — bottom-anchored panel (matches the native RootLayout
|
|
478
1839
|
sheet). Layer is pointer-events:none; backdrop + panel re-enable. */
|
|
479
1840
|
.vx-sheet-layer {
|
|
480
|
-
position: fixed;
|
|
481
|
-
inset: 0;
|
|
482
1841
|
z-index: 1100;
|
|
483
|
-
pointer-events: none;
|
|
484
1842
|
}
|
|
485
1843
|
|
|
486
1844
|
.vx-sheet-backdrop {
|
|
487
|
-
|
|
488
|
-
inset: 0;
|
|
489
|
-
background: rgba(15, 23, 42, 0.45);
|
|
490
|
-
pointer-events: auto;
|
|
1845
|
+
background: rgba(0, 0, 0, 0.4);
|
|
491
1846
|
}
|
|
492
1847
|
|
|
493
1848
|
.vx-sheet {
|
|
494
|
-
position: absolute;
|
|
495
|
-
left: 0;
|
|
496
|
-
right: 0;
|
|
497
|
-
bottom: 0;
|
|
498
1849
|
max-height: 85%;
|
|
499
1850
|
padding: 24px;
|
|
500
|
-
|
|
1851
|
+
border-width: 1px;
|
|
1852
|
+
border-color: var(--color-border);
|
|
501
1853
|
border-top-left-radius: var(--radius-xl);
|
|
502
1854
|
border-top-right-radius: var(--radius-xl);
|
|
503
1855
|
corner-shape: squircle;
|
|
504
1856
|
background-color: var(--color-surface);
|
|
505
1857
|
color: var(--color-text);
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1860
|
+
/* xplat-web-only:start — DOM positioning + hit-testing for the sheet.
|
|
1861
|
+
The native leaf renders on RootLayout with its own geometry. */
|
|
1862
|
+
.vx-sheet-layer {
|
|
1863
|
+
position: fixed;
|
|
1864
|
+
inset: 0;
|
|
1865
|
+
pointer-events: none;
|
|
1866
|
+
}
|
|
1867
|
+
|
|
1868
|
+
.vx-sheet-backdrop,
|
|
1869
|
+
.vx-sheet {
|
|
1870
|
+
position: absolute;
|
|
1871
|
+
inset: 0;
|
|
506
1872
|
pointer-events: auto;
|
|
507
1873
|
}
|
|
1874
|
+
|
|
1875
|
+
.vx-sheet {
|
|
1876
|
+
top: auto;
|
|
1877
|
+
bottom: 0;
|
|
1878
|
+
overflow: auto;
|
|
1879
|
+
}
|
|
1880
|
+
/* xplat-web-only:end */
|
|
1881
|
+
|
|
1882
|
+
.vx-sheet-grabber {
|
|
1883
|
+
display: flex;
|
|
1884
|
+
align-items: center;
|
|
1885
|
+
justify-content: center;
|
|
1886
|
+
height: 28px;
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1889
|
+
.vx-sheet-grip {
|
|
1890
|
+
width: 36px;
|
|
1891
|
+
height: 4px;
|
|
1892
|
+
border-radius: 999px;
|
|
1893
|
+
background-color: var(--color-text-secondary);
|
|
1894
|
+
opacity: 0.4;
|
|
1895
|
+
}
|
|
1896
|
+
|
|
1897
|
+
/* xplat-web-only:start — detents size the panel to the largest fraction
|
|
1898
|
+
(overriding the 85% cap) and overlay the grabber; native stacks it as a
|
|
1899
|
+
top-aligned grid child. touch-action keeps drags off native scroll. */
|
|
1900
|
+
.vx-sheet-detents {
|
|
1901
|
+
max-height: none;
|
|
1902
|
+
}
|
|
1903
|
+
.vx-sheet-detents > .vx-sheet-grabber {
|
|
1904
|
+
position: absolute;
|
|
1905
|
+
top: 0;
|
|
1906
|
+
left: 0;
|
|
1907
|
+
right: 0;
|
|
1908
|
+
z-index: 2;
|
|
1909
|
+
cursor: grab;
|
|
1910
|
+
touch-action: none;
|
|
1911
|
+
}
|
|
1912
|
+
/* xplat-web-only:end */
|