@stonedogcode/style 0.9.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/LICENSE +201 -0
- package/NOTICE +18 -0
- package/README.md +699 -0
- package/package.json +95 -0
- package/src/components/DictationControls.tsx +141 -0
- package/src/components/DictationPrompt.tsx +78 -0
- package/src/components/StyledBox.tsx +174 -0
- package/src/components/StyledButton.tsx +144 -0
- package/src/components/StyledCollapsible.tsx +127 -0
- package/src/components/StyledDefinitionList.tsx +134 -0
- package/src/components/StyledFieldset.tsx +157 -0
- package/src/components/StyledFlex.tsx +13 -0
- package/src/components/StyledFooter.tsx +399 -0
- package/src/components/StyledFormLabel.tsx +141 -0
- package/src/components/StyledGrid.tsx +109 -0
- package/src/components/StyledGridItem.tsx +19 -0
- package/src/components/StyledHStack.tsx +145 -0
- package/src/components/StyledHeading.tsx +79 -0
- package/src/components/StyledHrRule.tsx +33 -0
- package/src/components/StyledIcon.tsx +172 -0
- package/src/components/StyledIconButton.tsx +135 -0
- package/src/components/StyledInputBool.tsx +81 -0
- package/src/components/StyledInputRadio.tsx +141 -0
- package/src/components/StyledInputSelect.tsx +115 -0
- package/src/components/StyledInputSlider.tsx +83 -0
- package/src/components/StyledInputText.tsx +146 -0
- package/src/components/StyledInputTextArea.tsx +119 -0
- package/src/components/StyledInputToggle.tsx +224 -0
- package/src/components/StyledList.tsx +188 -0
- package/src/components/StyledScrollbar.tsx +53 -0
- package/src/components/StyledSearch.tsx +78 -0
- package/src/components/StyledSeparator.tsx +38 -0
- package/src/components/StyledSidebar.tsx +555 -0
- package/src/components/StyledSimpleGrid.tsx +99 -0
- package/src/components/StyledSparkLine.tsx +119 -0
- package/src/components/StyledSpinner.tsx +91 -0
- package/src/components/StyledStack.tsx +62 -0
- package/src/components/StyledText.tsx +99 -0
- package/src/components/StyledTooltip.tsx +398 -0
- package/src/components/StyledVStack.tsx +143 -0
- package/src/components/TitleLogo.tsx +223 -0
- package/src/components/create-icon.tsx +66 -0
- package/src/components/create-intent-button.tsx +134 -0
- package/src/components/dictation.ts +71 -0
- package/src/components/intent-buttons.ts +154 -0
- package/src/config/can-hover.ts +75 -0
- package/src/config/density.ts +138 -0
- package/src/config/font-size.ts +113 -0
- package/src/config/intent-icons.tsx +116 -0
- package/src/config/logger.ts +60 -0
- package/src/config/style-config.tsx +263 -0
- package/src/config/types.ts +137 -0
- package/src/index.ts +259 -0
- package/src/preset/index.ts +243 -0
- package/src/preset/recipes/arrows.ts +29 -0
- package/src/preset/recipes/box.ts +122 -0
- package/src/preset/recipes/button.ts +161 -0
- package/src/preset/recipes/dl-list.ts +109 -0
- package/src/preset/recipes/drawer.ts +125 -0
- package/src/preset/recipes/form.ts +95 -0
- package/src/preset/recipes/icon-button.ts +161 -0
- package/src/preset/recipes/icon.ts +34 -0
- package/src/preset/recipes/input-bool.ts +184 -0
- package/src/preset/recipes/input-dropdown.ts +93 -0
- package/src/preset/recipes/input-radio.ts +158 -0
- package/src/preset/recipes/input-surface.ts +152 -0
- package/src/preset/recipes/input-text.ts +17 -0
- package/src/preset/recipes/list.ts +196 -0
- package/src/preset/recipes/menu.ts +28 -0
- package/src/preset/recipes/separator.ts +89 -0
- package/src/preset/recipes/stack.ts +89 -0
- package/src/preset/recipes/striped.ts +34 -0
- package/src/preset/recipes/text.ts +41 -0
- package/src/preset/recipes/tooltip.ts +77 -0
- package/src/preset/semantic-variables.ts +283 -0
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { definePreset } from "@pandacss/dev";
|
|
2
|
+
|
|
3
|
+
import { arrowRecipe } from "./recipes/arrows";
|
|
4
|
+
import { boxRecipe } from "./recipes/box";
|
|
5
|
+
import { buttonRecipe } from "./recipes/button";
|
|
6
|
+
import { buttonIconRecipe } from "./recipes/icon-button";
|
|
7
|
+
import { dlRecipe } from "./recipes/dl-list";
|
|
8
|
+
import { drawerRecipe } from "./recipes/drawer";
|
|
9
|
+
import { formRecipe } from "./recipes/form";
|
|
10
|
+
import { iconRecipe } from "./recipes/icon";
|
|
11
|
+
import { inputBoolRecipe } from "./recipes/input-bool";
|
|
12
|
+
import {
|
|
13
|
+
inputDropdownContentRecipe,
|
|
14
|
+
inputDropdownItemRecipe,
|
|
15
|
+
inputDropdownRecipe,
|
|
16
|
+
} from "./recipes/input-dropdown";
|
|
17
|
+
import { inputRadioRootRecipe } from "./recipes/input-radio";
|
|
18
|
+
import { inputTextRecipe } from "./recipes/input-text";
|
|
19
|
+
import { listRecipe } from "./recipes/list";
|
|
20
|
+
import { menuRecipe } from "./recipes/menu";
|
|
21
|
+
import {
|
|
22
|
+
separatorHorizontalRecipe,
|
|
23
|
+
separatorVerticalRecipe,
|
|
24
|
+
} from "./recipes/separator";
|
|
25
|
+
import { stackRecipe } from "./recipes/stack";
|
|
26
|
+
import { stripedRecipe } from "./recipes/striped";
|
|
27
|
+
import { textRecipe } from "./recipes/text";
|
|
28
|
+
import { tooltipRecipe } from "./recipes/tooltip";
|
|
29
|
+
|
|
30
|
+
import {
|
|
31
|
+
DEFAULT_CSS_VAR_PREFIX,
|
|
32
|
+
createSemanticColors,
|
|
33
|
+
createSemanticFontWeights,
|
|
34
|
+
createSemanticFonts,
|
|
35
|
+
createSemanticSizes,
|
|
36
|
+
} from "./semantic-variables";
|
|
37
|
+
|
|
38
|
+
export interface StonedogStylePresetOptions {
|
|
39
|
+
/**
|
|
40
|
+
* Namespace for the CSS custom properties the colour tokens read.
|
|
41
|
+
*
|
|
42
|
+
* `"hopper"` yields `var(--hopper-box-primary-bg)`; `"optima"` yields
|
|
43
|
+
* `var(--optima-box-primary-bg)`. Only change this if the host application
|
|
44
|
+
* emits its theme under a different namespace — the value must match whatever
|
|
45
|
+
* writes those properties at runtime, and a mismatch renders every colour as
|
|
46
|
+
* nothing at all (see semantic-variables.ts).
|
|
47
|
+
*
|
|
48
|
+
* @default "hopper"
|
|
49
|
+
*/
|
|
50
|
+
cssVarPrefix?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Every recipe, keyed by the name it is exported under in `styled-system/recipes`.
|
|
55
|
+
*
|
|
56
|
+
* Four of these (`listRecipe`, `menuRecipe`, `inputBoolRecipe`,
|
|
57
|
+
* `inputRadioRootRecipe`) are slot recipes declared with `defineSlotRecipe`.
|
|
58
|
+
* Panda accepts them here rather than under `slotRecipes` and generates them
|
|
59
|
+
* correctly — verified against HopperGuard's own generated output. Moving them
|
|
60
|
+
* to `slotRecipes` would be more "correct" by the docs and would change the
|
|
61
|
+
* generated surface, so it is deliberately not done during extraction.
|
|
62
|
+
*/
|
|
63
|
+
const recipes = {
|
|
64
|
+
arrowRecipe,
|
|
65
|
+
boxRecipe,
|
|
66
|
+
buttonRecipe,
|
|
67
|
+
buttonIconRecipe,
|
|
68
|
+
dlRecipe,
|
|
69
|
+
drawerRecipe,
|
|
70
|
+
formRecipe,
|
|
71
|
+
iconRecipe,
|
|
72
|
+
inputBoolRecipe,
|
|
73
|
+
inputDropdownRecipe,
|
|
74
|
+
inputDropdownContentRecipe,
|
|
75
|
+
inputDropdownItemRecipe,
|
|
76
|
+
inputRadioRootRecipe,
|
|
77
|
+
inputTextRecipe,
|
|
78
|
+
listRecipe,
|
|
79
|
+
menuRecipe,
|
|
80
|
+
separatorHorizontalRecipe,
|
|
81
|
+
separatorVerticalRecipe,
|
|
82
|
+
stackRecipe,
|
|
83
|
+
stripedRecipe,
|
|
84
|
+
textRecipe,
|
|
85
|
+
tooltipRecipe,
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Force every variant of every recipe into the stylesheet.
|
|
90
|
+
*
|
|
91
|
+
* The style variant (`solid | outline | aurora | glass | matte`) is chosen by
|
|
92
|
+
* the *user* at runtime, not by the code, so Panda's static extractor has no way
|
|
93
|
+
* to know which classes will be needed — it only ever sees `variant={variant}`.
|
|
94
|
+
* Without this, switching variants at runtime yields elements with class names
|
|
95
|
+
* that have no corresponding CSS, which fails as an unstyled component rather
|
|
96
|
+
* than as an error.
|
|
97
|
+
*/
|
|
98
|
+
const staticCssRecipes = Object.fromEntries(
|
|
99
|
+
Object.keys(recipes).map((name) => [name, ["*"]]),
|
|
100
|
+
) as Record<keyof typeof recipes, ["*"]>;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Force the flexbox alignment utilities into the stylesheet (NEH-288).
|
|
104
|
+
*
|
|
105
|
+
* Same reasoning as the recipes above, one layer down. `StyledHStack` and
|
|
106
|
+
* `StyledVStack` accept `align`/`justify` as aliases and rename them to
|
|
107
|
+
* `alignItems`/`justifyContent` at runtime. Panda's extractor only reads source
|
|
108
|
+
* text: it sees `align="baseline"`, finds no utility by that name, and generates
|
|
109
|
+
* nothing — yet the component emits `ai_baseline`. Same for any value the caller
|
|
110
|
+
* computes rather than writes as a literal.
|
|
111
|
+
*
|
|
112
|
+
* That is this package's recurring failure mode: a class name with no rule
|
|
113
|
+
* behind it, which produces no build error, no console warning, and renders as
|
|
114
|
+
* silently-wrong layout. Fourteen declarations is a cheap price for closing it.
|
|
115
|
+
*/
|
|
116
|
+
const staticCssAlignment = [
|
|
117
|
+
{
|
|
118
|
+
properties: {
|
|
119
|
+
alignItems: ["flex-start", "flex-end", "center", "baseline", "stretch", "start", "end"],
|
|
120
|
+
justifyContent: [
|
|
121
|
+
"flex-start",
|
|
122
|
+
"flex-end",
|
|
123
|
+
"center",
|
|
124
|
+
"space-between",
|
|
125
|
+
"space-around",
|
|
126
|
+
"space-evenly",
|
|
127
|
+
"start",
|
|
128
|
+
"end",
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
];
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* The @stonedogcode/style Panda preset: colour tokens, breakpoints, keyframes, and
|
|
136
|
+
* the 22 recipes the component library is built on.
|
|
137
|
+
*
|
|
138
|
+
* Deliberately does NOT set `globalCss`, `preflight`, `include`, or `outdir` —
|
|
139
|
+
* those are application decisions, and a preset that quietly restyles `body` is
|
|
140
|
+
* a preset that is hard to adopt. The consuming app owns them. See CLAUDE.md.
|
|
141
|
+
*/
|
|
142
|
+
export function stonedogStylePreset(options: StonedogStylePresetOptions = {}) {
|
|
143
|
+
const { cssVarPrefix = DEFAULT_CSS_VAR_PREFIX } = options;
|
|
144
|
+
|
|
145
|
+
return definePreset({
|
|
146
|
+
name: "@stonedogcode/style",
|
|
147
|
+
theme: {
|
|
148
|
+
extend: {
|
|
149
|
+
/**
|
|
150
|
+
* The full responsive scale, declared here rather than only the one
|
|
151
|
+
* value that differs from Panda's default.
|
|
152
|
+
*
|
|
153
|
+
* The originating app declared only `3xl` and inherited `sm`–`2xl` from
|
|
154
|
+
* `@pandacss/preset-panda`. That works right up until a consumer passes
|
|
155
|
+
* a `presets` array — which **replaces** Panda's defaults rather than
|
|
156
|
+
* adding to them — at which point `md` silently stops being a valid
|
|
157
|
+
* breakpoint and every responsive prop in the library becomes a type
|
|
158
|
+
* error, or worse, a dropped style. Restating all six makes the preset
|
|
159
|
+
* self-sufficient for the values its components actually reference.
|
|
160
|
+
*
|
|
161
|
+
* The base presets are still required for tokens and utilities — see
|
|
162
|
+
* the consumer wiring in CLAUDE.md.
|
|
163
|
+
*/
|
|
164
|
+
breakpoints: {
|
|
165
|
+
sm: "640px",
|
|
166
|
+
md: "768px",
|
|
167
|
+
lg: "1024px",
|
|
168
|
+
xl: "1280px",
|
|
169
|
+
"2xl": "1536px",
|
|
170
|
+
"3xl": "1600px",
|
|
171
|
+
},
|
|
172
|
+
tokens: {
|
|
173
|
+
colors: createSemanticColors(cssVarPrefix),
|
|
174
|
+
sizes: createSemanticSizes(cssVarPrefix),
|
|
175
|
+
/**
|
|
176
|
+
* The host's typeface (NEH-289). `fontWeights` deliberately reuses
|
|
177
|
+
* Panda's own token names, so the `fontWeight: "bold"` already
|
|
178
|
+
* written across seven recipes starts reading the theme without a
|
|
179
|
+
* call site moving. Both carry fallbacks — see semantic-variables.
|
|
180
|
+
*/
|
|
181
|
+
fonts: createSemanticFonts(cssVarPrefix),
|
|
182
|
+
fontWeights: createSemanticFontWeights(cssVarPrefix),
|
|
183
|
+
},
|
|
184
|
+
keyframes: {
|
|
185
|
+
spin: {
|
|
186
|
+
"0%": { transform: "rotate(0deg)" },
|
|
187
|
+
"100%": { transform: "rotate(360deg)" },
|
|
188
|
+
},
|
|
189
|
+
// The disabled strike-through on StyledInputToggle. A keyframe rather
|
|
190
|
+
// than a transition because it plays once on appearance, and there is
|
|
191
|
+
// no "before" state to transition from.
|
|
192
|
+
stonedogStrikeIn: {
|
|
193
|
+
"0%": { transform: "scaleX(0)" },
|
|
194
|
+
"100%": { transform: "scaleX(1)" },
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
recipes,
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
staticCss: {
|
|
201
|
+
recipes: staticCssRecipes,
|
|
202
|
+
css: staticCssAlignment,
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export {
|
|
208
|
+
DEFAULT_CSS_VAR_PREFIX,
|
|
209
|
+
TEXT_BACKGROUND_PAIRS,
|
|
210
|
+
colorTokenNames,
|
|
211
|
+
createSemanticColors,
|
|
212
|
+
createSemanticFontWeights,
|
|
213
|
+
createSemanticFonts,
|
|
214
|
+
createSemanticSizes,
|
|
215
|
+
fontTokenNames,
|
|
216
|
+
fontWeightTokenNames,
|
|
217
|
+
getBackgroundForText,
|
|
218
|
+
requiredCssCustomProperties,
|
|
219
|
+
} from "./semantic-variables";
|
|
220
|
+
|
|
221
|
+
export { recipes as stonedogStyleRecipes };
|
|
222
|
+
|
|
223
|
+
/* ------------------------------------------------------------------------- *
|
|
224
|
+
* Deprecated `hopper*` aliases — NEH-251.
|
|
225
|
+
*
|
|
226
|
+
* The package renamed hopper-style → @stonedogcode/style. These re-exports exist so
|
|
227
|
+
* each consumer can bump its submodule pointer on its own schedule instead of
|
|
228
|
+
* every repo having to move in one lockstep sweep, which is what would make an
|
|
229
|
+
* ordered set of PRs impossible.
|
|
230
|
+
*
|
|
231
|
+
* They are a migration seam with an end date, not a compatibility promise.
|
|
232
|
+
* Remove them once HopperGuard, optima-filings and optima-cloud-saas have all
|
|
233
|
+
* landed their consumer PRs.
|
|
234
|
+
* ------------------------------------------------------------------------- */
|
|
235
|
+
|
|
236
|
+
/** @deprecated Renamed to `stonedogStylePreset`. Removed once every consumer has migrated (NEH-251). */
|
|
237
|
+
export const hopperStylePreset = stonedogStylePreset;
|
|
238
|
+
|
|
239
|
+
/** @deprecated Renamed to `StonedogStylePresetOptions`. Removed once every consumer has migrated (NEH-251). */
|
|
240
|
+
export type HopperStylePresetOptions = StonedogStylePresetOptions;
|
|
241
|
+
|
|
242
|
+
/** @deprecated Renamed to `stonedogStyleRecipes`. Removed once every consumer has migrated (NEH-251). */
|
|
243
|
+
export { recipes as hopperStyleRecipes };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { defineRecipe } from "@pandacss/dev";
|
|
2
|
+
|
|
3
|
+
export const arrowRecipe = defineRecipe({
|
|
4
|
+
className: "arrow",
|
|
5
|
+
description: "The style for an arrow",
|
|
6
|
+
base: {
|
|
7
|
+
width: "0",
|
|
8
|
+
height: "0",
|
|
9
|
+
},
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
solid: {
|
|
13
|
+
"--arrow-color": "red",
|
|
14
|
+
},
|
|
15
|
+
outline: {
|
|
16
|
+
"--arrow-color": "red",
|
|
17
|
+
},
|
|
18
|
+
aurora: {
|
|
19
|
+
"--arrow-color": "red",
|
|
20
|
+
},
|
|
21
|
+
glass: {
|
|
22
|
+
"--arrow-color": "red",
|
|
23
|
+
},
|
|
24
|
+
matte: {
|
|
25
|
+
"--arrow-color": "red",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
});
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { defineRecipe } from "@pandacss/dev";
|
|
2
|
+
|
|
3
|
+
export const boxRecipe = defineRecipe({
|
|
4
|
+
className: "box",
|
|
5
|
+
description: "The styles for the Box component",
|
|
6
|
+
base: {
|
|
7
|
+
display: "flex",
|
|
8
|
+
flexDirection: "column",
|
|
9
|
+
width: "100%",
|
|
10
|
+
},
|
|
11
|
+
variants: {
|
|
12
|
+
variant: {
|
|
13
|
+
none: {
|
|
14
|
+
border: "none",
|
|
15
|
+
backgroundColor: "transparent",
|
|
16
|
+
},
|
|
17
|
+
unstyled: {
|
|
18
|
+
border: "none",
|
|
19
|
+
backgroundColor: "transparent",
|
|
20
|
+
},
|
|
21
|
+
solid: {
|
|
22
|
+
px: { base: 6, md: 8 },
|
|
23
|
+
py: { base: 2, md: 4 },
|
|
24
|
+
bg: "boxBgPrimary",
|
|
25
|
+
color: "textPrimary",
|
|
26
|
+
},
|
|
27
|
+
outline: {
|
|
28
|
+
px: { base: 6, md: 8 },
|
|
29
|
+
py: { base: 2, md: 4 },
|
|
30
|
+
border: "1px solid",
|
|
31
|
+
borderColor: "borderBgSecondary",
|
|
32
|
+
color: "textPrimary",
|
|
33
|
+
bg: "boxBgPrimary",
|
|
34
|
+
},
|
|
35
|
+
link: {
|
|
36
|
+
bg: "boxBgPrimary",
|
|
37
|
+
_hover: {
|
|
38
|
+
textDecoration: "underline",
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
aurora: {
|
|
42
|
+
px: { base: 6, md: 8 },
|
|
43
|
+
py: { base: 2, md: 4 },
|
|
44
|
+
border: "1px solid",
|
|
45
|
+
borderRadius: "md",
|
|
46
|
+
backgroundImage: "linear-gradient(to right, #ff7e5f, #feb47b)",
|
|
47
|
+
color: "textPrimary",
|
|
48
|
+
borderColor: "borderBgSecondary",
|
|
49
|
+
},
|
|
50
|
+
glass: {
|
|
51
|
+
px: { base: 6, md: 8 },
|
|
52
|
+
py: { base: 2, md: 4 },
|
|
53
|
+
position: "relative",
|
|
54
|
+
overflow: "hidden",
|
|
55
|
+
borderRadius: "2xl", // more rounded for curved glass effect
|
|
56
|
+
borderWidth: "2px",
|
|
57
|
+
borderStyle: "solid",
|
|
58
|
+
bg: "boxBgSecondary/60",
|
|
59
|
+
color: "textPrimary",
|
|
60
|
+
boxShadow: "xl",
|
|
61
|
+
fontWeight: "bold",
|
|
62
|
+
borderColor: "borderBgPrimary/10",
|
|
63
|
+
_before: {
|
|
64
|
+
content: '""',
|
|
65
|
+
position: "absolute",
|
|
66
|
+
top: 0,
|
|
67
|
+
left: 0,
|
|
68
|
+
right: 0,
|
|
69
|
+
bottom: 0,
|
|
70
|
+
borderRadius: "inherit",
|
|
71
|
+
bgGradient:
|
|
72
|
+
"linear(to-br, rgba(255,255,255,0.08), rgba(255,255,255,0.02))",
|
|
73
|
+
zIndex: -1,
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
matte: {
|
|
77
|
+
px: { base: 6, md: 8 },
|
|
78
|
+
py: { base: 2, md: 4 },
|
|
79
|
+
bgGradient: "linear(to-b, gray.800, gray.900)",
|
|
80
|
+
borderColor: "gray.700",
|
|
81
|
+
borderWidth: "1px",
|
|
82
|
+
boxShadow: "md",
|
|
83
|
+
/**
|
|
84
|
+
* `whiteAlpha.900` was undefined vocabulary, so this never painted and
|
|
85
|
+
* matte text inherited whatever it landed on — dark-on-dark against
|
|
86
|
+
* the fixed gradient above (NEH-301).
|
|
87
|
+
*
|
|
88
|
+
* `white`, not a token, and that is deliberate. The surface here is
|
|
89
|
+
* `gray.800`→`gray.900`: a FIXED dark gradient that does not follow the
|
|
90
|
+
* host's theme. Pointing the text at a host token while the surface
|
|
91
|
+
* stays fixed is how you get dark-on-dark in a light theme — a
|
|
92
|
+
* contrast regression traded for a style-rule win. The literal is the
|
|
93
|
+
* honest description of what matte currently is, and it joins the
|
|
94
|
+
* tracked literal-colour cleanup (`gray.*`, `black`/`white` in
|
|
95
|
+
* input-text.ts) that has to move the surface and the text together.
|
|
96
|
+
*/
|
|
97
|
+
color: "white",
|
|
98
|
+
borderRadius: "lg",
|
|
99
|
+
fontWeight: "bold",
|
|
100
|
+
},
|
|
101
|
+
ghost: {
|
|
102
|
+
px: { base: 6, md: 8 },
|
|
103
|
+
py: { base: 2, md: 4 },
|
|
104
|
+
color: "textSecondary",
|
|
105
|
+
bg: "boxBgSecondary",
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
layout: {
|
|
109
|
+
vertical: {}, // Base is already vertical
|
|
110
|
+
horizontal: {
|
|
111
|
+
flexDirection: { base: "column", lg: "row" },
|
|
112
|
+
gap: 4,
|
|
113
|
+
alignItems: "center",
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
clickable: {
|
|
117
|
+
true: {
|
|
118
|
+
cursor: "pointer",
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
});
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { defineRecipe } from "@pandacss/dev";
|
|
2
|
+
|
|
3
|
+
export const buttonRecipe = defineRecipe({
|
|
4
|
+
className: "button",
|
|
5
|
+
base: {
|
|
6
|
+
display: "inline-flex",
|
|
7
|
+
alignItems: "center",
|
|
8
|
+
justifyContent: "center",
|
|
9
|
+
// A `<button>` does not inherit the page font — see input-surface (NEH-289).
|
|
10
|
+
fontFamily: "body",
|
|
11
|
+
fontWeight: "semibold",
|
|
12
|
+
padding: "calc(.2rem + var(--panda-density-padding, 8px))",
|
|
13
|
+
/**
|
|
14
|
+
* The tap-target floor, enforced structurally (NEH-220, NEH-251).
|
|
15
|
+
*
|
|
16
|
+
* Until now this recipe set no minimum and the button's size *emerged*
|
|
17
|
+
* from padding plus the inherited font size. That looked fine and was not:
|
|
18
|
+
* a short label produced a 42.375px-tall control against a 44px
|
|
19
|
+
* requirement, and the two component tests asserting the floor were marked
|
|
20
|
+
* `test.fail()` — the requirement was documented, visible, and unmet.
|
|
21
|
+
*
|
|
22
|
+
* Emergent sizing is also fragile in a way a constant is not. The font
|
|
23
|
+
* scale is host-tunable and just moved (md 1.375rem -> 1rem), which drops
|
|
24
|
+
* every button that depends on font size for its height. A floor that
|
|
25
|
+
* survives a typography change has to be stated, not derived.
|
|
26
|
+
*/
|
|
27
|
+
minHeight: "48px",
|
|
28
|
+
minWidth: "48px",
|
|
29
|
+
_hover: {
|
|
30
|
+
cursor: "pointer",
|
|
31
|
+
},
|
|
32
|
+
border: "1px solid",
|
|
33
|
+
borderColor: "borderBgPrimary",
|
|
34
|
+
borderRadius: "var(--radii-md, 0.375rem)",
|
|
35
|
+
},
|
|
36
|
+
variants: {
|
|
37
|
+
variant: {
|
|
38
|
+
solid: {
|
|
39
|
+
bg: "buttonBgAccent",
|
|
40
|
+
color: "textPrimary",
|
|
41
|
+
_hover: {
|
|
42
|
+
bg: "buttonBgSecondary",
|
|
43
|
+
color: "textPrimary",
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
outline: {
|
|
47
|
+
bg: "buttonBgAccent",
|
|
48
|
+
border: "2px solid",
|
|
49
|
+
borderRadius: 0,
|
|
50
|
+
_hover: {
|
|
51
|
+
border: "2px solid",
|
|
52
|
+
bg: "buttonBgAccentHover",
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
aurora: {
|
|
56
|
+
backgroundImage: "linear-gradient(to right, #ff7e5f, #feb47b)",
|
|
57
|
+
color: "buttonTextPrimary",
|
|
58
|
+
_hover: {
|
|
59
|
+
opacity: 0.9,
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
glass: {
|
|
63
|
+
position: "relative",
|
|
64
|
+
overflow: "hidden",
|
|
65
|
+
border: "2px solid",
|
|
66
|
+
borderRadius: "xl",
|
|
67
|
+
bg: "buttonBgAccent",
|
|
68
|
+
color: "textPrimary",
|
|
69
|
+
boxShadow: "0 8px 32px rgba(0,0,0,0.2)",
|
|
70
|
+
backdropFilter: "blur(12px)",
|
|
71
|
+
WebkitBackdropFilter: "blur(12px)",
|
|
72
|
+
fontWeight: "bold",
|
|
73
|
+
lineHeight: "shorter",
|
|
74
|
+
transition: "all 0.3s ease",
|
|
75
|
+
_hover: {
|
|
76
|
+
bg: "buttonBgSecondary",
|
|
77
|
+
borderColor: "rgba(255,255,255,0.4)",
|
|
78
|
+
boxShadow: "0 8px 32px rgba(0,0,0,0.3), inset 0 0 20px rgba(255,255,255,0.1)",
|
|
79
|
+
transform: "translateY(-1px)",
|
|
80
|
+
textDecoration: "none",
|
|
81
|
+
},
|
|
82
|
+
_active: {
|
|
83
|
+
transform: "translateY(0)",
|
|
84
|
+
bg: "rgba(255,255,255,0.15)",
|
|
85
|
+
},
|
|
86
|
+
_before: {
|
|
87
|
+
content: '""',
|
|
88
|
+
position: "absolute",
|
|
89
|
+
top: 0,
|
|
90
|
+
left: 0,
|
|
91
|
+
right: 0,
|
|
92
|
+
bottom: "50%",
|
|
93
|
+
borderRadius: "inherit",
|
|
94
|
+
bg: "linear-gradient(to bottom, rgba(255,255,255,0.15), transparent)",
|
|
95
|
+
zIndex: 0,
|
|
96
|
+
pointerEvents: "none",
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
matte: {
|
|
100
|
+
bgGradient: "linear(to-b, gray.800, gray.900)",
|
|
101
|
+
borderColor: "gray.700",
|
|
102
|
+
borderWidth: "1px",
|
|
103
|
+
boxShadow: "md",
|
|
104
|
+
bg: "buttonBgAccent",
|
|
105
|
+
color: "textPrimary",
|
|
106
|
+
borderRadius: "lg",
|
|
107
|
+
fontWeight: "bold",
|
|
108
|
+
},
|
|
109
|
+
ghost: {
|
|
110
|
+
bg: "boxBgSecondary/90",
|
|
111
|
+
color: "textPrimary",
|
|
112
|
+
_hover: {
|
|
113
|
+
bg: "boxBgSecondary",
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
selected: {
|
|
117
|
+
color: "textPrimary",
|
|
118
|
+
border: "3px dashed black",
|
|
119
|
+
borderRadius: "xl",
|
|
120
|
+
bg: "boxBgAccent",
|
|
121
|
+
},
|
|
122
|
+
none: {
|
|
123
|
+
color: "textMain",
|
|
124
|
+
bg: "white"
|
|
125
|
+
},
|
|
126
|
+
unstyled: {
|
|
127
|
+
color: "inherit",
|
|
128
|
+
border: "none",
|
|
129
|
+
backgroundColor: "transparent",
|
|
130
|
+
},
|
|
131
|
+
link: {
|
|
132
|
+
color: "textMain",
|
|
133
|
+
/**
|
|
134
|
+
* Stated, not omitted (NEH-307).
|
|
135
|
+
*
|
|
136
|
+
* A `<button>` that declares no background does not render
|
|
137
|
+
* transparent — the user agent paints its own `ButtonFace`, a system
|
|
138
|
+
* grey that ignores the theme and moves with the browser's colour
|
|
139
|
+
* scheme (measured: `rgb(239,239,239)` light, `rgb(107,107,107)`
|
|
140
|
+
* dark). This preset sets `preflight: false` and imposes no reset on
|
|
141
|
+
* its consumers, so there is nothing between this recipe and the UA's
|
|
142
|
+
* paint except this line. `unstyled` has always said it; `link` was
|
|
143
|
+
* the only one of the ten variants that did not.
|
|
144
|
+
*
|
|
145
|
+
* Transparent is the right answer for a link-styled button — the
|
|
146
|
+
* themed surface behind it should show through — but silence gets the
|
|
147
|
+
* browser's grey, not transparency.
|
|
148
|
+
*/
|
|
149
|
+
backgroundColor: "transparent",
|
|
150
|
+
border: "1px solid transparent",
|
|
151
|
+
textDecoration: "underline",
|
|
152
|
+
_hover: {
|
|
153
|
+
color: "buttonTextAccent",
|
|
154
|
+
},
|
|
155
|
+
_active: {
|
|
156
|
+
color: "buttonTextSecondary",
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
});
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { defineRecipe } from "@pandacss/dev";
|
|
2
|
+
|
|
3
|
+
export const dlRecipe = defineRecipe({
|
|
4
|
+
className: "dl-list",
|
|
5
|
+
base: {
|
|
6
|
+
border: "1px solid",
|
|
7
|
+
borderRadius: "md",
|
|
8
|
+
// Was a literal `purple` (NEH-301): it rendered, but it was the same
|
|
9
|
+
// purple in every theme and in every colour mode. The row separators
|
|
10
|
+
// below already use this token — the outer border had simply never been
|
|
11
|
+
// moved onto it.
|
|
12
|
+
borderColor: "borderBgPrimary",
|
|
13
|
+
// Add vertical padding and margin between dt/dd pairs
|
|
14
|
+
"& > dt, & > dd": {
|
|
15
|
+
paddingTop: "0.5rem",
|
|
16
|
+
paddingBottom: "0.5rem",
|
|
17
|
+
},
|
|
18
|
+
"& > dt:not(:first-child), & > dd:not(:first-child)": {
|
|
19
|
+
marginTop: "0.5rem",
|
|
20
|
+
},
|
|
21
|
+
// The separator was `& > li`, which a `<dl>` never contains — the rule was
|
|
22
|
+
// valid, and matched nothing, so the row separators had never once
|
|
23
|
+
// rendered (NEH-167, cycle 9). `dd` puts the line after each completed
|
|
24
|
+
// pair; `dt` would have drawn it between a term and its own definition.
|
|
25
|
+
//
|
|
26
|
+
// Merged into the existing `dd` rule rather than added beside it: a second
|
|
27
|
+
// key with the same selector is a duplicate object key, and the later one
|
|
28
|
+
// replaces the earlier wholesale — which would have dropped this margin.
|
|
29
|
+
"& > dd:not(:last-child)": {
|
|
30
|
+
marginBottom: "0.5rem",
|
|
31
|
+
borderBottom: "1px solid",
|
|
32
|
+
borderColor: "borderBgPrimary",
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
variants: {
|
|
36
|
+
variant: {
|
|
37
|
+
solid: {
|
|
38
|
+
// `bgAccent` was Chakra vocabulary this package never defined, so the
|
|
39
|
+
// surface never painted (NEH-301). `textAccent` rather than
|
|
40
|
+
// `textPrimary` because TEXT_BACKGROUND_PAIRS is what a host's
|
|
41
|
+
// contrast check reads: text on `boxBgAccent` must be `textAccent`, or
|
|
42
|
+
// the pair that gets validated is not the pair that renders.
|
|
43
|
+
bg: "boxBgAccent",
|
|
44
|
+
color: "textAccent",
|
|
45
|
+
borderColor: "borderBgPrimary",
|
|
46
|
+
},
|
|
47
|
+
outline: {
|
|
48
|
+
borderColor: "borderBgSecondary",
|
|
49
|
+
color: "textPrimary",
|
|
50
|
+
"& > dd:not(:last-child)": {
|
|
51
|
+
borderBottom: "1px solid",
|
|
52
|
+
borderColor: "borderBgSecondary",
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
aurora: {
|
|
56
|
+
// The token names were QUOTED, so they were CSS strings, so the whole
|
|
57
|
+
// gradient was invalid and this variant had no background at all
|
|
58
|
+
// (NEH-301). `{colors.X}` is the syntax that actually substitutes a
|
|
59
|
+
// token inside an arbitrary value — see drawerRecipe, the one aurora
|
|
60
|
+
// that has been rendering. Surface tokens, not `textPrimary`: this is
|
|
61
|
+
// a background.
|
|
62
|
+
backgroundImage: `linear-gradient(to right, {colors.boxBgAccent}, {colors.boxBgSecondary})`,
|
|
63
|
+
color: "textPrimary",
|
|
64
|
+
borderColor: "transparent",
|
|
65
|
+
"& > dd:not(:last-child)": {
|
|
66
|
+
borderBottom: "1px solid",
|
|
67
|
+
borderColor: "borderBgPrimary",
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
glass: {
|
|
71
|
+
backdropFilter: "blur(10px)",
|
|
72
|
+
backgroundColor: "rgba(255, 255, 255, 0.1)",
|
|
73
|
+
border: "1px solid rgba(255, 255, 255, 0.2)",
|
|
74
|
+
color: "textPrimary",
|
|
75
|
+
"& > dd:not(:last-child)": {
|
|
76
|
+
borderBottom: "1px solid rgba(255, 255, 255, 0.2)",
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
matte: {
|
|
80
|
+
// `secondary` was undefined vocabulary — the surface never painted
|
|
81
|
+
// (NEH-301). Paired text, per TEXT_BACKGROUND_PAIRS.
|
|
82
|
+
bg: "boxBgSecondary",
|
|
83
|
+
color: "textSecondary",
|
|
84
|
+
borderColor: "borderBgPrimary",
|
|
85
|
+
"& > dd:not(:last-child)": {
|
|
86
|
+
borderBottom: "1px solid",
|
|
87
|
+
borderColor: "borderBgPrimary",
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
none: {
|
|
91
|
+
border: "none",
|
|
92
|
+
backgroundColor: "inherit",
|
|
93
|
+
"& > dd:not(:last-child)": {
|
|
94
|
+
borderBottom: "1px solid",
|
|
95
|
+
borderColor: "borderBgPrimary",
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
unstyled: {
|
|
99
|
+
border: "none",
|
|
100
|
+
p: "0",
|
|
101
|
+
m: "0",
|
|
102
|
+
backgroundColor: "inherit",
|
|
103
|
+
"& > dd:not(:last-child)": {
|
|
104
|
+
borderBottom: "none",
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
});
|