@olympusoss/canvas 4.0.0 → 5.0.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 +108 -0
- package/package.json +14 -3
- package/src/atoms/avatar/avatar.md +185 -0
- package/src/atoms/avatar/avatar.styles.ts +48 -0
- package/src/atoms/avatar/avatar.tsx +99 -0
- package/src/atoms/badge/badge.md +237 -0
- package/src/atoms/badge/badge.styles.ts +79 -0
- package/src/atoms/badge/badge.tsx +86 -0
- package/src/atoms/breadcrumb/breadcrumb.md +233 -0
- package/src/atoms/breadcrumb/breadcrumb.styles.ts +40 -0
- package/src/atoms/breadcrumb/breadcrumb.tsx +130 -0
- package/src/atoms/button/button.android.tsx +6 -0
- package/src/atoms/button/button.ios.tsx +6 -0
- package/src/atoms/button/button.md +184 -0
- package/src/atoms/button/button.shared.tsx +79 -0
- package/src/atoms/button/button.styles.ts +152 -0
- package/src/atoms/button/button.tsx +6 -0
- package/src/atoms/button-group/button-group.android.tsx +6 -0
- package/src/atoms/button-group/button-group.ios.tsx +6 -0
- package/src/atoms/button-group/button-group.md +120 -0
- package/src/atoms/button-group/button-group.shared.tsx +398 -0
- package/src/atoms/button-group/button-group.styles.ts +483 -0
- package/src/atoms/button-group/button-group.tsx +6 -0
- package/src/atoms/checkbox/checkbox.android.tsx +6 -0
- package/src/atoms/checkbox/checkbox.ios.tsx +6 -0
- package/src/atoms/checkbox/checkbox.md +150 -0
- package/src/atoms/checkbox/checkbox.shared.tsx +103 -0
- package/src/atoms/checkbox/checkbox.styles.ts +106 -0
- package/src/atoms/checkbox/checkbox.tsx +6 -0
- package/src/atoms/combobox/combobox.android.tsx +6 -0
- package/src/atoms/combobox/combobox.ios.tsx +6 -0
- package/src/atoms/combobox/combobox.md +213 -0
- package/src/atoms/combobox/combobox.shared.tsx +160 -0
- package/src/atoms/combobox/combobox.styles.ts +270 -0
- package/src/atoms/combobox/combobox.tsx +6 -0
- package/src/atoms/divider/divider.md +140 -0
- package/src/atoms/divider/divider.styles.ts +35 -0
- package/src/atoms/divider/divider.tsx +67 -0
- package/src/atoms/dropdown/dropdown.android.tsx +6 -0
- package/src/atoms/dropdown/dropdown.ios.tsx +6 -0
- package/src/atoms/dropdown/dropdown.md +221 -0
- package/src/atoms/dropdown/dropdown.shared.tsx +190 -0
- package/src/atoms/dropdown/dropdown.styles.ts +233 -0
- package/src/atoms/dropdown/dropdown.tsx +6 -0
- package/src/atoms/icon/icon.md +131 -0
- package/src/atoms/icon/icon.styles.ts +30 -0
- package/src/atoms/icon/icon.tsx +328 -0
- package/src/atoms/index.ts +24 -0
- package/src/atoms/input/input.android.tsx +6 -0
- package/src/atoms/input/input.ios.tsx +6 -0
- package/src/atoms/input/input.md +118 -0
- package/src/atoms/input/input.shared.tsx +203 -0
- package/src/atoms/input/input.styles.ts +286 -0
- package/src/atoms/input/input.tsx +6 -0
- package/src/atoms/kbd/kbd.md +91 -0
- package/src/atoms/kbd/kbd.styles.ts +33 -0
- package/src/atoms/kbd/kbd.tsx +27 -0
- package/src/atoms/listbox/listbox.md +177 -0
- package/src/atoms/listbox/listbox.styles.ts +60 -0
- package/src/atoms/listbox/listbox.tsx +113 -0
- package/src/atoms/pagination/pagination.android.tsx +6 -0
- package/src/atoms/pagination/pagination.ios.tsx +6 -0
- package/src/atoms/pagination/pagination.md +133 -0
- package/src/atoms/pagination/pagination.shared.tsx +289 -0
- package/src/atoms/pagination/pagination.styles.ts +245 -0
- package/src/atoms/pagination/pagination.tsx +6 -0
- package/src/atoms/popover/popover.android.tsx +8 -0
- package/src/atoms/popover/popover.ios.tsx +6 -0
- package/src/atoms/popover/popover.md +87 -0
- package/src/atoms/popover/popover.shared.tsx +124 -0
- package/src/atoms/popover/popover.styles.ts +144 -0
- package/src/atoms/popover/popover.tsx +6 -0
- package/src/atoms/radio/radio.android.tsx +6 -0
- package/src/atoms/radio/radio.ios.tsx +6 -0
- package/src/atoms/radio/radio.md +173 -0
- package/src/atoms/radio/radio.shared.tsx +98 -0
- package/src/atoms/radio/radio.styles.ts +109 -0
- package/src/atoms/radio/radio.tsx +6 -0
- package/src/atoms/select/select.android.tsx +6 -0
- package/src/atoms/select/select.ios.tsx +6 -0
- package/src/atoms/select/select.md +156 -0
- package/src/atoms/select/select.shared.tsx +143 -0
- package/src/atoms/select/select.styles.ts +310 -0
- package/src/atoms/select/select.tsx +6 -0
- package/src/atoms/skeleton/skeleton.md +135 -0
- package/src/atoms/skeleton/skeleton.styles.ts +117 -0
- package/src/atoms/skeleton/skeleton.tsx +145 -0
- package/src/atoms/spinner/spinner.android.tsx +7 -0
- package/src/atoms/spinner/spinner.ios.tsx +7 -0
- package/src/atoms/spinner/spinner.md +94 -0
- package/src/atoms/spinner/spinner.shared.tsx +92 -0
- package/src/atoms/spinner/spinner.styles.tsx +115 -0
- package/src/atoms/spinner/spinner.tsx +7 -0
- package/src/atoms/switch/switch.android.tsx +6 -0
- package/src/atoms/switch/switch.ios.tsx +6 -0
- package/src/atoms/switch/switch.md +91 -0
- package/src/atoms/switch/switch.shared.tsx +97 -0
- package/src/atoms/switch/switch.styles.ts +79 -0
- package/src/atoms/switch/switch.tsx +6 -0
- package/src/atoms/textarea/textarea.android.tsx +6 -0
- package/src/atoms/textarea/textarea.ios.tsx +6 -0
- package/src/atoms/textarea/textarea.md +140 -0
- package/src/atoms/textarea/textarea.shared.tsx +74 -0
- package/src/atoms/textarea/textarea.styles.ts +116 -0
- package/src/atoms/textarea/textarea.tsx +6 -0
- package/src/atoms/tooltip/tooltip.android.tsx +6 -0
- package/src/atoms/tooltip/tooltip.ios.tsx +7 -0
- package/src/atoms/tooltip/tooltip.md +122 -0
- package/src/atoms/tooltip/tooltip.shared.tsx +113 -0
- package/src/atoms/tooltip/tooltip.styles.ts +113 -0
- package/src/atoms/tooltip/tooltip.tsx +6 -0
- package/src/atoms/typography/typography.md +330 -0
- package/src/atoms/typography/typography.styles.ts +95 -0
- package/src/atoms/typography/typography.tsx +76 -0
- package/src/index.ts +12 -2
- package/src/molecules/action-panels/action-panels.md +133 -0
- package/src/molecules/action-panels/action-panels.styles.ts +39 -0
- package/src/molecules/action-panels/action-panels.tsx +113 -0
- package/src/molecules/alert/alert.md +119 -0
- package/src/molecules/alert/alert.styles.ts +88 -0
- package/src/molecules/alert/alert.tsx +74 -0
- package/src/molecules/alert-dialog/alert-dialog.android.tsx +6 -0
- package/src/molecules/alert-dialog/alert-dialog.ios.tsx +6 -0
- package/src/molecules/alert-dialog/alert-dialog.md +177 -0
- package/src/molecules/alert-dialog/alert-dialog.shared.tsx +187 -0
- package/src/molecules/alert-dialog/alert-dialog.styles.ts +248 -0
- package/src/molecules/alert-dialog/alert-dialog.tsx +6 -0
- package/src/molecules/card/card.md +190 -0
- package/src/molecules/card/card.styles.ts +67 -0
- package/src/molecules/card/card.tsx +176 -0
- package/src/molecules/code-block/code-block.md +159 -0
- package/src/molecules/code-block/code-block.styles.ts +167 -0
- package/src/molecules/code-block/code-block.tsx +176 -0
- package/src/molecules/description-lists/description-lists.md +129 -0
- package/src/molecules/description-lists/description-lists.styles.ts +102 -0
- package/src/molecules/description-lists/description-lists.tsx +133 -0
- package/src/molecules/empty-state/empty-state.md +218 -0
- package/src/molecules/empty-state/empty-state.styles.ts +63 -0
- package/src/molecules/empty-state/empty-state.tsx +77 -0
- package/src/molecules/feeds/feeds.md +102 -0
- package/src/molecules/feeds/feeds.styles.ts +120 -0
- package/src/molecules/feeds/feeds.tsx +167 -0
- package/src/molecules/field/field.md +117 -0
- package/src/molecules/field/field.styles.ts +85 -0
- package/src/molecules/field/field.tsx +175 -0
- package/src/molecules/fieldset/fieldset.md +141 -0
- package/src/molecules/fieldset/fieldset.styles.ts +79 -0
- package/src/molecules/fieldset/fieldset.tsx +182 -0
- package/src/molecules/form/form.md +137 -0
- package/src/molecules/form/form.styles.ts +39 -0
- package/src/molecules/form/form.tsx +246 -0
- package/src/molecules/grid-lists/grid-lists.md +114 -0
- package/src/molecules/grid-lists/grid-lists.styles.ts +79 -0
- package/src/molecules/grid-lists/grid-lists.tsx +157 -0
- package/src/molecules/index.ts +16 -0
- package/src/molecules/media-objects/media-objects.md +87 -0
- package/src/molecules/media-objects/media-objects.styles.ts +94 -0
- package/src/molecules/media-objects/media-objects.tsx +128 -0
- package/src/molecules/stacked-lists/stacked-lists.md +116 -0
- package/src/molecules/stacked-lists/stacked-lists.styles.ts +111 -0
- package/src/molecules/stacked-lists/stacked-lists.tsx +195 -0
- package/src/molecules/stats/stats.md +166 -0
- package/src/molecules/stats/stats.styles.ts +91 -0
- package/src/molecules/stats/stats.tsx +88 -0
- package/src/organisms/calendar/calendar.android.tsx +6 -0
- package/src/organisms/calendar/calendar.ios.tsx +6 -0
- package/src/organisms/calendar/calendar.md +114 -0
- package/src/organisms/calendar/calendar.shared.tsx +146 -0
- package/src/organisms/calendar/calendar.styles.ts +315 -0
- package/src/organisms/calendar/calendar.tsx +6 -0
- package/src/organisms/charts/charts.md +326 -0
- package/src/organisms/charts/charts.styles.ts +135 -0
- package/src/organisms/charts/charts.tsx +124 -0
- package/src/organisms/command/command.md +117 -0
- package/src/organisms/command/command.styles.ts +179 -0
- package/src/organisms/command/command.tsx +164 -0
- package/src/organisms/data-table/data-table.md +182 -0
- package/src/organisms/data-table/data-table.styles.ts +103 -0
- package/src/organisms/data-table/data-table.tsx +105 -0
- package/src/organisms/dialog/dialog.android.tsx +6 -0
- package/src/organisms/dialog/dialog.ios.tsx +6 -0
- package/src/organisms/dialog/dialog.md +271 -0
- package/src/organisms/dialog/dialog.shared.tsx +230 -0
- package/src/organisms/dialog/dialog.styles.ts +272 -0
- package/src/organisms/dialog/dialog.tsx +6 -0
- package/src/organisms/filter-panel/filter-panel.md +116 -0
- package/src/organisms/filter-panel/filter-panel.styles.ts +83 -0
- package/src/organisms/filter-panel/filter-panel.tsx +91 -0
- package/src/organisms/index.ts +13 -0
- package/src/organisms/navbars/navbars.android.tsx +6 -0
- package/src/organisms/navbars/navbars.ios.tsx +6 -0
- package/src/organisms/navbars/navbars.md +144 -0
- package/src/organisms/navbars/navbars.shared.tsx +137 -0
- package/src/organisms/navbars/navbars.styles.ts +251 -0
- package/src/organisms/navbars/navbars.tsx +6 -0
- package/src/organisms/overlays/overlays.android.tsx +6 -0
- package/src/organisms/overlays/overlays.ios.tsx +6 -0
- package/src/organisms/overlays/overlays.md +123 -0
- package/src/organisms/overlays/overlays.shared.tsx +175 -0
- package/src/organisms/overlays/overlays.styles.ts +309 -0
- package/src/organisms/overlays/overlays.tsx +6 -0
- package/src/organisms/row-menu/row-menu.android.tsx +6 -0
- package/src/organisms/row-menu/row-menu.ios.tsx +6 -0
- package/src/organisms/row-menu/row-menu.md +102 -0
- package/src/organisms/row-menu/row-menu.shared.tsx +105 -0
- package/src/organisms/row-menu/row-menu.styles.ts +262 -0
- package/src/organisms/row-menu/row-menu.tsx +6 -0
- package/src/organisms/sidebar/sidebar.android.tsx +6 -0
- package/src/organisms/sidebar/sidebar.ios.tsx +6 -0
- package/src/organisms/sidebar/sidebar.md +188 -0
- package/src/organisms/sidebar/sidebar.shared.tsx +167 -0
- package/src/organisms/sidebar/sidebar.styles.ts +262 -0
- package/src/organisms/sidebar/sidebar.tsx +6 -0
- package/src/organisms/stepper/stepper.android.tsx +6 -0
- package/src/organisms/stepper/stepper.ios.tsx +6 -0
- package/src/organisms/stepper/stepper.md +150 -0
- package/src/organisms/stepper/stepper.shared.tsx +158 -0
- package/src/organisms/stepper/stepper.styles.ts +280 -0
- package/src/organisms/stepper/stepper.tsx +6 -0
- package/src/organisms/tabs/tabs.android.tsx +6 -0
- package/src/organisms/tabs/tabs.ios.tsx +6 -0
- package/src/organisms/tabs/tabs.md +127 -0
- package/src/organisms/tabs/tabs.shared.tsx +281 -0
- package/src/organisms/tabs/tabs.styles.ts +398 -0
- package/src/organisms/tabs/tabs.tsx +6 -0
- package/src/style/color.ts +17 -0
- package/src/style/index.ts +14 -0
- package/src/style/primitives.ts +26 -0
- package/src/style/responsive.ts +45 -0
- package/src/style/shadow.ts +21 -0
- package/src/style/theme.tsx +56 -0
- package/src/style/tokens.ts +487 -0
- package/src/theme.ts +21 -0
- package/styles/canvas.css +128 -67
- package/tsconfig.json +4 -2
- package/src/cn.ts +0 -3
- package/styles/base.css +0 -17
- package/styles/components/alert.css +0 -66
- package/styles/components/app-shell.css +0 -46
- package/styles/components/avatar.css +0 -15
- package/styles/components/badge.css +0 -83
- package/styles/components/breadcrumb.css +0 -35
- package/styles/components/button-group.css +0 -23
- package/styles/components/button.css +0 -107
- package/styles/components/calendar.css +0 -73
- package/styles/components/card.css +0 -58
- package/styles/components/checkbox.css +0 -55
- package/styles/components/code-block.css +0 -18
- package/styles/components/combobox.css +0 -75
- package/styles/components/command.css +0 -94
- package/styles/components/data-table.css +0 -142
- package/styles/components/dialog.css +0 -72
- package/styles/components/dropdown.css +0 -54
- package/styles/components/empty-state.css +0 -17
- package/styles/components/field.css +0 -27
- package/styles/components/filter-panel.css +0 -58
- package/styles/components/form.css +0 -27
- package/styles/components/icon.css +0 -8
- package/styles/components/input-group.css +0 -45
- package/styles/components/input.css +0 -56
- package/styles/components/kbd.css +0 -15
- package/styles/components/page-header.css +0 -52
- package/styles/components/pagination.css +0 -48
- package/styles/components/popover.css +0 -14
- package/styles/components/radio.css +0 -28
- package/styles/components/row-menu.css +0 -69
- package/styles/components/section-card.css +0 -49
- package/styles/components/select.css +0 -57
- package/styles/components/separator.css +0 -32
- package/styles/components/sheet.css +0 -70
- package/styles/components/sidebar.css +0 -146
- package/styles/components/skeleton.css +0 -32
- package/styles/components/spinner.css +0 -26
- package/styles/components/stat-card.css +0 -71
- package/styles/components/stepper.css +0 -63
- package/styles/components/switch.css +0 -45
- package/styles/components/tabs.css +0 -40
- package/styles/components/textarea.css +0 -31
- package/styles/components/toast.css +0 -95
- package/styles/components/tooltip.css +0 -53
- package/styles/components/topbar.css +0 -24
- package/styles/components/typography.css +0 -105
- package/styles/patterns/backdrops.css +0 -35
- package/styles/patterns/density.css +0 -66
- package/styles/patterns/focus.css +0 -38
- package/styles/patterns/glass.css +0 -85
- package/styles/patterns/high-contrast.css +0 -70
- package/styles/patterns/reduced-motion.css +0 -12
- package/styles/patterns/scrollbar.css +0 -10
- package/styles/reset.css +0 -89
- package/styles/tokens/colors.css +0 -106
- package/styles/tokens/motion.css +0 -33
- package/styles/tokens/radius.css +0 -10
- package/styles/tokens/shadows.css +0 -35
- package/styles/tokens/spacing.css +0 -19
- package/styles/tokens/typography.css +0 -6
- package/styles/tokens/z-index.css +0 -12
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { type ViewStyle, type TextStyle } from "react-native";
|
|
2
|
+
import { type ColorTokens, shadow } from "../../style/index.js";
|
|
3
|
+
|
|
4
|
+
// Co-located Card styles. Layout-only parts are static objects; anything that
|
|
5
|
+
// reads a color is a function of the active tokens (so the surface follows
|
|
6
|
+
// light/dark, and reads as glass when the ThemeProvider's surface is "glass",
|
|
7
|
+
// since tokens.card is swapped translucent at the theming level).
|
|
8
|
+
|
|
9
|
+
export type Elevation = "raised" | "flat" | "default";
|
|
10
|
+
export type Density = "compact" | "comfortable" | "default";
|
|
11
|
+
|
|
12
|
+
export const cardBase: ViewStyle = { borderRadius: 8, borderWidth: 1 };
|
|
13
|
+
|
|
14
|
+
// The card surface fill + border. tokens.card goes translucent under glass.
|
|
15
|
+
export function cardSurface(tokens: ColorTokens): ViewStyle {
|
|
16
|
+
return { borderColor: tokens.border, backgroundColor: tokens.card };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Elevation: raised lifts the shadow, flat drops it, default is the soft shadow.
|
|
20
|
+
export function elevation(e: Elevation): ViewStyle {
|
|
21
|
+
return e === "raised" ? shadow("md") : e === "flat" ? shadow("none") : shadow("sm");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Density sets the card's own content padding and the gap between flat children.
|
|
25
|
+
export const density: Record<Density, ViewStyle> = {
|
|
26
|
+
compact: { padding: 16, gap: 12 },
|
|
27
|
+
comfortable: { padding: 32, gap: 24 },
|
|
28
|
+
default: {},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// The standard inset applied by `padded` when no density is set.
|
|
32
|
+
export const padded: ViewStyle = { padding: 24 };
|
|
33
|
+
|
|
34
|
+
// --- subcomponent styles ----------------------------------------------------
|
|
35
|
+
|
|
36
|
+
export const header: ViewStyle = { gap: 6, paddingHorizontal: 20, paddingBottom: 16, paddingTop: 20 };
|
|
37
|
+
|
|
38
|
+
export function title(tokens: ColorTokens): TextStyle {
|
|
39
|
+
return { fontSize: 20, lineHeight: 28, fontWeight: "600", letterSpacing: -0.4, color: tokens["card-foreground"] };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function description(tokens: ColorTokens): TextStyle {
|
|
43
|
+
return { fontSize: 14, lineHeight: 20, color: tokens["muted-foreground"] };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const content: ViewStyle = { paddingHorizontal: 20, paddingVertical: 20 };
|
|
47
|
+
|
|
48
|
+
export const footer: ViewStyle = {
|
|
49
|
+
flexDirection: "row",
|
|
50
|
+
alignItems: "center",
|
|
51
|
+
gap: 8,
|
|
52
|
+
paddingHorizontal: 20,
|
|
53
|
+
paddingBottom: 20,
|
|
54
|
+
paddingTop: 16,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export function separator(tokens: ColorTokens): ViewStyle {
|
|
58
|
+
return { height: 1, width: "100%", backgroundColor: tokens.border };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function bodyText(tokens: ColorTokens): TextStyle {
|
|
62
|
+
return { fontSize: 14, lineHeight: 20, color: tokens["card-foreground"] };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function footerText(tokens: ColorTokens): TextStyle {
|
|
66
|
+
return { fontSize: 14, lineHeight: 20, color: tokens["muted-foreground"] };
|
|
67
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { View, Pressable, Text, useTheme, type StyleProp, type ViewStyle, type TextStyle } from "../../style/index.js";
|
|
3
|
+
import * as s from "./card.styles.js";
|
|
4
|
+
import { type Elevation, type Density } from "./card.styles.js";
|
|
5
|
+
|
|
6
|
+
// Card: a surface container. The base surface gives you the border, radius, and
|
|
7
|
+
// shadow; you bring the content. Structure is composed from the subcomponents
|
|
8
|
+
// (CardHeader, CardTitle, CardDescription, CardContent, CardFooter), with a
|
|
9
|
+
// hairline CardSeparator anchoring a header above a body.
|
|
10
|
+
//
|
|
11
|
+
// Boolean-prop API: one boolean per option, grouped by axis, first-match
|
|
12
|
+
// precedence within an axis (mirrors Button's intentOf). Axes:
|
|
13
|
+
//
|
|
14
|
+
// - Elevation (pick one): `raised` > `flat` > default (shadow-sm). `flat`
|
|
15
|
+
// drops the shadow; `raised` lifts it to shadow-md.
|
|
16
|
+
// - Interaction: `interactive` (with onPress) gives a pressed affordance, for a
|
|
17
|
+
// card that behaves like a control.
|
|
18
|
+
// - Padding: `padded` pads the surface itself (good for a single block of
|
|
19
|
+
// content); omit when you compose CardHeader/CardContent, which carry their
|
|
20
|
+
// own padding.
|
|
21
|
+
// - Density (pick one): `compact` > `comfortable`. Sets the card's own content
|
|
22
|
+
// padding and the gap between flat children, tight (compact) or roomy
|
|
23
|
+
// (comfortable). A density prop pads the surface on its own, so it needs no
|
|
24
|
+
// `padded`, and it wins over `padded` when both are set.
|
|
25
|
+
//
|
|
26
|
+
// For the docs playground, which maps plain state to props (no JSX children),
|
|
27
|
+
// Card also accepts simple string props (title, description, body, footer):
|
|
28
|
+
// when no children are passed it renders the header/body/footer structure from
|
|
29
|
+
// those strings, so a representative card can be produced from flat state.
|
|
30
|
+
|
|
31
|
+
export interface CardProps {
|
|
32
|
+
children?: ReactNode;
|
|
33
|
+
// Simple content props for the children-less / data-driven case.
|
|
34
|
+
title?: string;
|
|
35
|
+
description?: string;
|
|
36
|
+
body?: string;
|
|
37
|
+
footer?: string;
|
|
38
|
+
// Elevation (pick one; default is a soft shadow-sm).
|
|
39
|
+
raised?: boolean;
|
|
40
|
+
flat?: boolean;
|
|
41
|
+
// Interaction and padding (orthogonal booleans).
|
|
42
|
+
interactive?: boolean;
|
|
43
|
+
padded?: boolean;
|
|
44
|
+
/** When set, the whole card becomes pressable (a card that behaves as a control). */
|
|
45
|
+
onPress?: () => void;
|
|
46
|
+
// Density (pick one; default is the standard inset). Scales the card's own
|
|
47
|
+
// content padding and the gap between flat children.
|
|
48
|
+
compact?: boolean;
|
|
49
|
+
comfortable?: boolean;
|
|
50
|
+
/** Escape hatch for layout/positioning composition (width, margins). */
|
|
51
|
+
style?: StyleProp<ViewStyle>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Elevation precedence when more than one is passed: first match wins.
|
|
55
|
+
function elevationOf(p: CardProps): Elevation {
|
|
56
|
+
if (p.raised) return "raised";
|
|
57
|
+
if (p.flat) return "flat";
|
|
58
|
+
return "default";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Density precedence when more than one is passed: first match wins.
|
|
62
|
+
function densityOf(p: CardProps): Density {
|
|
63
|
+
if (p.compact) return "compact";
|
|
64
|
+
if (p.comfortable) return "comfortable";
|
|
65
|
+
return "default";
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function Card(props: CardProps) {
|
|
69
|
+
const { children, title, description, body, footer, padded, onPress, style } = props;
|
|
70
|
+
const { tokens } = useTheme();
|
|
71
|
+
const elev = elevationOf(props);
|
|
72
|
+
const dens = densityOf(props);
|
|
73
|
+
|
|
74
|
+
const container: StyleProp<ViewStyle> = [
|
|
75
|
+
s.cardBase,
|
|
76
|
+
s.cardSurface(tokens),
|
|
77
|
+
s.elevation(elev),
|
|
78
|
+
// Density pads + gaps on its own and wins over `padded`; otherwise `padded`
|
|
79
|
+
// applies the standard inset, and a bare card stays unpadded for composition.
|
|
80
|
+
dens !== "default" ? s.density[dens] : padded ? s.padded : null,
|
|
81
|
+
style,
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
// Children win: when composed, render exactly what the caller passed.
|
|
85
|
+
// Otherwise build a representative structure from the simple string props.
|
|
86
|
+
let inner: ReactNode;
|
|
87
|
+
if (children != null) {
|
|
88
|
+
inner = children;
|
|
89
|
+
} else {
|
|
90
|
+
const hasHeader = title != null || description != null;
|
|
91
|
+
inner = (
|
|
92
|
+
<>
|
|
93
|
+
{hasHeader ? (
|
|
94
|
+
<CardHeader>
|
|
95
|
+
{title != null ? <CardTitle>{title}</CardTitle> : null}
|
|
96
|
+
{description != null ? <CardDescription>{description}</CardDescription> : null}
|
|
97
|
+
</CardHeader>
|
|
98
|
+
) : null}
|
|
99
|
+
{hasHeader && body != null ? <CardSeparator /> : null}
|
|
100
|
+
{body != null ? (
|
|
101
|
+
<CardContent>
|
|
102
|
+
<Text style={s.bodyText(tokens)}>{body}</Text>
|
|
103
|
+
</CardContent>
|
|
104
|
+
) : null}
|
|
105
|
+
{footer != null ? (
|
|
106
|
+
<>
|
|
107
|
+
<CardSeparator />
|
|
108
|
+
<CardFooter>
|
|
109
|
+
<Text style={s.footerText(tokens)}>{footer}</Text>
|
|
110
|
+
</CardFooter>
|
|
111
|
+
</>
|
|
112
|
+
) : null}
|
|
113
|
+
</>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// A pressable card swaps View for Pressable, adding the pressed affordance.
|
|
118
|
+
if (onPress) {
|
|
119
|
+
return (
|
|
120
|
+
<Pressable
|
|
121
|
+
accessibilityRole="button"
|
|
122
|
+
onPress={onPress}
|
|
123
|
+
style={({ pressed }) => [container, pressed ? { opacity: 0.9 } : null]}
|
|
124
|
+
>
|
|
125
|
+
{inner}
|
|
126
|
+
</Pressable>
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
return <View style={container}>{inner}</View>;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export interface CardSectionProps {
|
|
133
|
+
children?: ReactNode;
|
|
134
|
+
/** Escape hatch for layout/positioning composition. */
|
|
135
|
+
style?: StyleProp<ViewStyle>;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface CardTextProps {
|
|
139
|
+
children?: ReactNode;
|
|
140
|
+
/** Escape hatch for layout/positioning composition. */
|
|
141
|
+
style?: StyleProp<TextStyle>;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Header: the labeled top of the card, holding the title and description.
|
|
145
|
+
export function CardHeader({ children, style }: CardSectionProps) {
|
|
146
|
+
return <View style={[s.header, style]}>{children}</View>;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Title: the card's heading. Semibold, tight tracking, card foreground.
|
|
150
|
+
export function CardTitle({ children, style }: CardTextProps) {
|
|
151
|
+
const { tokens } = useTheme();
|
|
152
|
+
return <Text style={[s.title(tokens), style]}>{children}</Text>;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Description: the muted supporting line beneath the title.
|
|
156
|
+
export function CardDescription({ children, style }: CardTextProps) {
|
|
157
|
+
const { tokens } = useTheme();
|
|
158
|
+
return <Text style={[s.description(tokens), style]}>{children}</Text>;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Content: the card body region. Carries the standard surface padding.
|
|
162
|
+
export function CardContent({ children, style }: CardSectionProps) {
|
|
163
|
+
return <View style={[s.content, style]}>{children}</View>;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Footer: the bottom region for actions or a summary line.
|
|
167
|
+
export function CardFooter({ children, style }: CardSectionProps) {
|
|
168
|
+
return <View style={[s.footer, style]}>{children}</View>;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Separator: the hairline that anchors a header above a body. A card composing
|
|
172
|
+
// a header and body keeps this divider between them.
|
|
173
|
+
export function CardSeparator({ style }: { style?: StyleProp<ViewStyle> }) {
|
|
174
|
+
const { tokens } = useTheme();
|
|
175
|
+
return <View style={[s.separator(tokens), style]} />;
|
|
176
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Code Block
|
|
2
|
+
|
|
3
|
+
Preformatted code block with monospace font and padding.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
<CodeBlock
|
|
9
|
+
code={`const theme = getTheme();
|
|
10
|
+
setTheme(theme === "dark" ? "light" : "dark");`}
|
|
11
|
+
filename="theme.ts"
|
|
12
|
+
language="ts"
|
|
13
|
+
/>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Variants
|
|
17
|
+
|
|
18
|
+
### Variant - terminal
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
<CodeBlock
|
|
22
|
+
code={`const theme = getTheme();
|
|
23
|
+
setTheme(theme === "dark" ? "light" : "dark");`}
|
|
24
|
+
filename="theme.ts"
|
|
25
|
+
language="ts"
|
|
26
|
+
terminal
|
|
27
|
+
/>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Variant - numbered
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
<CodeBlock
|
|
34
|
+
code={`const theme = getTheme();
|
|
35
|
+
setTheme(theme === "dark" ? "light" : "dark");`}
|
|
36
|
+
filename="theme.ts"
|
|
37
|
+
language="ts"
|
|
38
|
+
numbered
|
|
39
|
+
/>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Variant - inline
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
<CodeBlock
|
|
46
|
+
code={`const theme = getTheme();
|
|
47
|
+
setTheme(theme === "dark" ? "light" : "dark");`}
|
|
48
|
+
filename="theme.ts"
|
|
49
|
+
language="ts"
|
|
50
|
+
inline
|
|
51
|
+
/>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Copy button
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
<CodeBlock
|
|
58
|
+
code={`const theme = getTheme();
|
|
59
|
+
setTheme(theme === "dark" ? "light" : "dark");`}
|
|
60
|
+
filename="theme.ts"
|
|
61
|
+
language="ts"
|
|
62
|
+
copy
|
|
63
|
+
/>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Wrap long lines
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
<CodeBlock
|
|
70
|
+
code={`const theme = getTheme();
|
|
71
|
+
setTheme(theme === "dark" ? "light" : "dark");`}
|
|
72
|
+
filename="theme.ts"
|
|
73
|
+
language="ts"
|
|
74
|
+
wrap
|
|
75
|
+
/>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Do & Don't
|
|
79
|
+
|
|
80
|
+
### Plain
|
|
81
|
+
|
|
82
|
+
**Do** — Use a pre element so whitespace, line breaks, and indentation survive verbatim.
|
|
83
|
+
|
|
84
|
+
```tsx
|
|
85
|
+
<CodeBlock code={`const theme = getTheme();
|
|
86
|
+
setTheme(theme === "dark" ? "light" : "dark");`} />
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Don't** — A paragraph collapses the line breaks and indentation, so multi-line code reads as one run-on string.
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
<View style={{ maxWidth: 360 }}>
|
|
93
|
+
<Text style={{ fontSize: 13, fontFamily: "monospace" }}>const theme = getTheme(); setTheme(theme === "dark" ? "light" : "dark");</Text>
|
|
94
|
+
</View>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Terminal
|
|
98
|
+
|
|
99
|
+
**Do** — Mark the prompt select-none so a copy yields only the command, not the shell glyph.
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
<CodeBlock terminal code="npm install @olympusoss/canvas" />
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Don't** — Selectable prompt text means a reader who copies the line drags the $ marker into their shell.
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
<View style={{ width: "100%", alignSelf: "flex-start", borderRadius: 8, backgroundColor: palette["zinc-900"], padding: 16 }}>
|
|
109
|
+
<Text style={{ fontSize: 13, color: palette["zinc-100"], fontFamily: "monospace" }}>$ npm install @olympusoss/canvas</Text>
|
|
110
|
+
</View>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Numbered
|
|
114
|
+
|
|
115
|
+
**Do** — Keep the gutter select-none so copying the block returns clean, runnable code.
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
<CodeBlock numbered code={`const theme = getTheme();
|
|
119
|
+
setTheme(theme);`} />
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Don't** — Selectable line numbers get swept into the selection and pasted as 1 2 ahead of every line.
|
|
123
|
+
|
|
124
|
+
```tsx
|
|
125
|
+
<View style={{ width: "100%", alignSelf: "flex-start", flexDirection: "row", borderRadius: 8, borderWidth: 1, borderColor: tokens.border, backgroundColor: alpha(tokens.muted, 0.5), padding: 16 }}>
|
|
126
|
+
<View style={{ marginRight: 16, alignItems: "flex-end" }}>
|
|
127
|
+
<Text style={{ fontSize: 14, lineHeight: 28, color: alpha(tokens["muted-foreground"], 0.5), fontFamily: "monospace" }}>1</Text>
|
|
128
|
+
<Text style={{ fontSize: 14, lineHeight: 28, color: alpha(tokens["muted-foreground"], 0.5), fontFamily: "monospace" }}>2</Text>
|
|
129
|
+
</View>
|
|
130
|
+
<View style={{ flexGrow: 1, flexShrink: 1, flexBasis: "0%" }}>
|
|
131
|
+
<Text style={{ fontSize: 14, lineHeight: 28, color: tokens.foreground, fontFamily: "monospace" }}>const theme = getTheme();</Text>
|
|
132
|
+
<Text style={{ fontSize: 14, lineHeight: 28, color: tokens.foreground, fontFamily: "monospace" }}>setTheme(theme);</Text>
|
|
133
|
+
</View>
|
|
134
|
+
</View>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Inline
|
|
138
|
+
|
|
139
|
+
**Do** — Reserve inline code for short tokens; move anything multi-line into a block.
|
|
140
|
+
|
|
141
|
+
```tsx
|
|
142
|
+
<View style={{ maxWidth: 360, gap: 6 }}>
|
|
143
|
+
<Text style={{ fontSize: 14, lineHeight: 28 }}>Run the setup command:</Text>
|
|
144
|
+
<CodeBlock code={`npm install @olympusoss/canvas
|
|
145
|
+
npm run build`} />
|
|
146
|
+
</View>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Don't** — A long, multi-step command crammed inline wraps mid-token and offers no horizontal scroll.
|
|
150
|
+
|
|
151
|
+
```tsx
|
|
152
|
+
<View style={{ maxWidth: 360, flexDirection: "row", flexWrap: "wrap", alignItems: "center" }}>
|
|
153
|
+
<Text style={{ fontSize: 14, lineHeight: 28, color: tokens.foreground }}>Run </Text>
|
|
154
|
+
<View style={{ alignSelf: "flex-start", borderRadius: 4, borderWidth: 1, borderColor: tokens.border, backgroundColor: tokens.muted, paddingHorizontal: 6, paddingVertical: 2 }}>
|
|
155
|
+
<Text style={{ fontSize: 13, color: tokens.foreground, fontFamily: "monospace" }}>npm install @olympusoss/canvas && npm run build && npm run preview</Text>
|
|
156
|
+
</View>
|
|
157
|
+
<Text style={{ fontSize: 14, lineHeight: 28, color: tokens.foreground }}> to start.</Text>
|
|
158
|
+
</View>
|
|
159
|
+
```
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { type ViewStyle, type TextStyle } from "react-native";
|
|
2
|
+
import { type ColorTokens, palette, shadow, alpha } from "../../style/index.js";
|
|
3
|
+
|
|
4
|
+
// Co-located CodeBlock styles. Layout-only fragments are static objects; anything
|
|
5
|
+
// that reads a color is a function of the active tokens, so the muted surface
|
|
6
|
+
// follows light/dark and reads as glass at the theming level. The terminal
|
|
7
|
+
// variant is intentionally a fixed dark window built from the Tailwind palette
|
|
8
|
+
// (zinc/emerald/red/amber/green), so it stays dark in every scheme.
|
|
9
|
+
|
|
10
|
+
export type Variant = "terminal" | "numbered" | "inline" | "plain";
|
|
11
|
+
|
|
12
|
+
// Monospace face: requested inline since RN has no font-family utility (the same
|
|
13
|
+
// approach Badge's `mono` modifier uses).
|
|
14
|
+
export const MONO = { fontFamily: "monospace" } as const;
|
|
15
|
+
|
|
16
|
+
// Shared code type: text-sm leading-relaxed.
|
|
17
|
+
export const codeType: TextStyle = { fontSize: 14, lineHeight: 28 };
|
|
18
|
+
|
|
19
|
+
// Code foreground color (text-foreground).
|
|
20
|
+
export function codeText(tokens: ColorTokens): TextStyle {
|
|
21
|
+
return { color: tokens.foreground };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// The shared code surface: a muted, bordered, rounded card. (w-full self-start
|
|
25
|
+
// rounded-lg border border-border bg-muted/50)
|
|
26
|
+
export function surface(tokens: ColorTokens): ViewStyle {
|
|
27
|
+
return {
|
|
28
|
+
width: "100%",
|
|
29
|
+
alignSelf: "flex-start",
|
|
30
|
+
borderRadius: 8,
|
|
31
|
+
borderWidth: 1,
|
|
32
|
+
borderColor: tokens.border,
|
|
33
|
+
backgroundColor: alpha(tokens.muted, 0.5),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Surface padding (p-4) added on top of `surface`.
|
|
38
|
+
export const surfacePad: ViewStyle = { padding: 16 };
|
|
39
|
+
|
|
40
|
+
// --- outer wrappers ---------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
// relative
|
|
43
|
+
export const relative: ViewStyle = { position: "relative" };
|
|
44
|
+
|
|
45
|
+
// --- inline variant ---------------------------------------------------------
|
|
46
|
+
|
|
47
|
+
// self-start rounded border border-border bg-muted px-1.5 py-0.5
|
|
48
|
+
export function inlineBox(tokens: ColorTokens): ViewStyle {
|
|
49
|
+
return {
|
|
50
|
+
alignSelf: "flex-start",
|
|
51
|
+
borderRadius: 4,
|
|
52
|
+
borderWidth: 1,
|
|
53
|
+
borderColor: tokens.border,
|
|
54
|
+
backgroundColor: tokens.muted,
|
|
55
|
+
paddingHorizontal: 6,
|
|
56
|
+
paddingVertical: 2,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// --- terminal variant -------------------------------------------------------
|
|
61
|
+
|
|
62
|
+
// relative w-full self-start overflow-hidden rounded-lg border border-border shadow-sm
|
|
63
|
+
export function terminalOuter(tokens: ColorTokens): ViewStyle {
|
|
64
|
+
return {
|
|
65
|
+
position: "relative",
|
|
66
|
+
width: "100%",
|
|
67
|
+
alignSelf: "flex-start",
|
|
68
|
+
overflow: "hidden",
|
|
69
|
+
borderRadius: 8,
|
|
70
|
+
borderWidth: 1,
|
|
71
|
+
borderColor: tokens.border,
|
|
72
|
+
...shadow("sm"),
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Chrome bar: flex-row items-center gap-1.5 border-b border-zinc-700 bg-zinc-800 px-4 py-2.5
|
|
77
|
+
export const terminalChrome: ViewStyle = {
|
|
78
|
+
flexDirection: "row",
|
|
79
|
+
alignItems: "center",
|
|
80
|
+
gap: 6,
|
|
81
|
+
borderBottomWidth: 1,
|
|
82
|
+
borderColor: palette["zinc-700"],
|
|
83
|
+
backgroundColor: palette["zinc-800"],
|
|
84
|
+
paddingHorizontal: 16,
|
|
85
|
+
paddingVertical: 10,
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// Traffic-light dot: h-3 w-3 rounded-full bg-<hue>-500.
|
|
89
|
+
export function trafficDot(hue: "red" | "amber" | "green"): ViewStyle {
|
|
90
|
+
return { height: 12, width: 12, borderRadius: 9999, backgroundColor: palette[`${hue}-500`] };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Chrome label: ml-2 text-xs text-zinc-400.
|
|
94
|
+
export const terminalLabel: TextStyle = {
|
|
95
|
+
marginLeft: 8,
|
|
96
|
+
fontSize: 12,
|
|
97
|
+
lineHeight: 16,
|
|
98
|
+
color: palette["zinc-400"],
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// Terminal body: bg-zinc-900 p-4.
|
|
102
|
+
export const terminalBody: ViewStyle = { backgroundColor: palette["zinc-900"], padding: 16 };
|
|
103
|
+
|
|
104
|
+
// A single command row: flex-row.
|
|
105
|
+
export const terminalRow: ViewStyle = { flexDirection: "row" };
|
|
106
|
+
|
|
107
|
+
// The non-selectable "$ " prompt: text-emerald-400.
|
|
108
|
+
export const terminalPrompt: TextStyle = { color: palette["emerald-400"] };
|
|
109
|
+
|
|
110
|
+
// The command line itself: flex-1 text-zinc-100.
|
|
111
|
+
export const terminalLine: TextStyle = {
|
|
112
|
+
flexGrow: 1,
|
|
113
|
+
flexShrink: 1,
|
|
114
|
+
flexBasis: "0%",
|
|
115
|
+
color: palette["zinc-100"],
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// --- numbered variant -------------------------------------------------------
|
|
119
|
+
|
|
120
|
+
// The numbered surface row: flex-row p-4 (on top of `surface`).
|
|
121
|
+
export const numberedSurface: ViewStyle = { flexDirection: "row", padding: 16 };
|
|
122
|
+
|
|
123
|
+
// The line-number gutter: mr-4 items-end.
|
|
124
|
+
export const numberedGutter: ViewStyle = { marginRight: 16, alignItems: "flex-end" };
|
|
125
|
+
|
|
126
|
+
// Dimmed line numbers (text-muted-foreground), sharing the code type.
|
|
127
|
+
export function gutterText(tokens: ColorTokens): TextStyle {
|
|
128
|
+
return { color: tokens["muted-foreground"] };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// The code column: flex-1.
|
|
132
|
+
export const numberedCodeCol: ViewStyle = { flexGrow: 1, flexShrink: 1, flexBasis: "0%" };
|
|
133
|
+
|
|
134
|
+
// --- copy affordance --------------------------------------------------------
|
|
135
|
+
|
|
136
|
+
// absolute right-2 top-2 z-10 flex-row items-center self-start rounded-md border px-2.5 py-1.
|
|
137
|
+
// The fill/border follows the dark branch: dark window vs light surface.
|
|
138
|
+
export function copyButton(tokens: ColorTokens, dark: boolean): ViewStyle {
|
|
139
|
+
const base: ViewStyle = {
|
|
140
|
+
position: "absolute",
|
|
141
|
+
right: 8,
|
|
142
|
+
top: 8,
|
|
143
|
+
zIndex: 10,
|
|
144
|
+
flexDirection: "row",
|
|
145
|
+
alignItems: "center",
|
|
146
|
+
alignSelf: "flex-start",
|
|
147
|
+
borderRadius: 6,
|
|
148
|
+
borderWidth: 1,
|
|
149
|
+
paddingHorizontal: 10,
|
|
150
|
+
paddingVertical: 4,
|
|
151
|
+
};
|
|
152
|
+
// The `dark` flag here is the CopyButton's own (terminal forces it); it picks
|
|
153
|
+
// the dark zinc chip vs the light background chip with a soft shadow.
|
|
154
|
+
return dark
|
|
155
|
+
? { ...base, borderColor: palette["zinc-700"], backgroundColor: palette["zinc-800"] }
|
|
156
|
+
: { ...base, borderColor: tokens.border, backgroundColor: tokens.background, ...shadow("sm") };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Copy label: text-xs font-medium, color per dark branch.
|
|
160
|
+
export function copyText(tokens: ColorTokens, dark: boolean): TextStyle {
|
|
161
|
+
return {
|
|
162
|
+
fontSize: 12,
|
|
163
|
+
lineHeight: 16,
|
|
164
|
+
fontWeight: "500",
|
|
165
|
+
color: dark ? palette["zinc-300"] : tokens["muted-foreground"],
|
|
166
|
+
};
|
|
167
|
+
}
|