Gates / frontend (push) Successful in 1m11s
Gates / test (push) Successful in 1m40s
Gates / test-aarch64 (push) Successful in 6m38s
Gates / package (push) Successful in 5m42s
Gates / container (push) Successful in 17s
CI / gates (push) Successful in 27m54s
the chart's screen-reader table wore srOnly directly; overflow and height do not apply to a table box, so it laid out 1200px tall below the page while clip-path hid the paint. wrap it in a hidden div, which clips properly and keeps the table role. failure detail is the diagnostics page's job since milestone 27; the column and the now dead formatAge go.
257 lines
6.9 KiB
TypeScript
257 lines
6.9 KiB
TypeScript
/**
|
|
* The shared style vocabulary (milestone 23, ruling 3; replaces the Tailwind
|
|
* class constants of milestone 18, ruling 10).
|
|
*
|
|
* Every interactive element must carry `focusRing` or `insetFocusRing`; that
|
|
* is the milestone-9 accessibility floor. Compose at the call site with
|
|
* `stylex.props(styles.button, extra)` instead of re-spelling a variant.
|
|
*/
|
|
|
|
import * as stylex from "@stylexjs/stylex";
|
|
import { colors } from "./tokens.stylex";
|
|
|
|
const FOCUS = ":focus-visible";
|
|
const DISABLED = ":disabled";
|
|
|
|
/** The half-fade loop a placeholder runs while its data is in flight. */
|
|
const pulseFrames = stylex.keyframes({
|
|
"50%": { opacity: 0.5 },
|
|
});
|
|
|
|
export const styles = stylex.create({
|
|
/** The ring drawn outside the element. */
|
|
focusRing: {
|
|
outlineWidth: { default: null, [FOCUS]: 2 },
|
|
outlineStyle: { default: null, [FOCUS]: "solid" },
|
|
outlineColor: { default: null, [FOCUS]: colors.focus },
|
|
outlineOffset: { default: null, [FOCUS]: 2 },
|
|
},
|
|
/** The ring drawn inside the element, for controls flush against a panel edge. */
|
|
insetFocusRing: {
|
|
outlineWidth: { default: null, [FOCUS]: 2 },
|
|
outlineStyle: { default: null, [FOCUS]: "solid" },
|
|
outlineColor: { default: null, [FOCUS]: colors.focus },
|
|
outlineOffset: { default: null, [FOCUS]: -2 },
|
|
},
|
|
|
|
input: {
|
|
marginTop: "0.25rem",
|
|
width: "100%",
|
|
borderRadius: "0.25rem",
|
|
borderWidth: 1,
|
|
borderStyle: "solid",
|
|
borderColor: colors.borderStrong,
|
|
backgroundColor: colors.surfaceRaised,
|
|
color: colors.text,
|
|
paddingInline: "0.75rem",
|
|
paddingBlock: "0.5rem",
|
|
},
|
|
smallInput: {
|
|
borderRadius: "0.25rem",
|
|
borderWidth: 1,
|
|
borderStyle: "solid",
|
|
borderColor: colors.borderStrong,
|
|
backgroundColor: colors.surfaceRaised,
|
|
color: colors.text,
|
|
paddingInline: "0.5rem",
|
|
paddingBlock: "0.375rem",
|
|
fontSize: "0.875rem",
|
|
lineHeight: "1.25rem",
|
|
},
|
|
|
|
button: {
|
|
borderRadius: "0.25rem",
|
|
borderWidth: 1,
|
|
borderStyle: "solid",
|
|
borderColor: colors.borderStrong,
|
|
paddingInline: "0.75rem",
|
|
paddingBlock: "0.375rem",
|
|
fontSize: "0.875rem",
|
|
lineHeight: "1.25rem",
|
|
},
|
|
smallButton: {
|
|
borderRadius: "0.25rem",
|
|
borderWidth: 1,
|
|
borderStyle: "solid",
|
|
borderColor: colors.borderStrong,
|
|
paddingInline: "0.5rem",
|
|
paddingBlock: "0.25rem",
|
|
fontSize: "0.875rem",
|
|
lineHeight: "1.25rem",
|
|
},
|
|
largeButton: {
|
|
borderRadius: "0.25rem",
|
|
borderWidth: 1,
|
|
borderStyle: "solid",
|
|
borderColor: colors.borderStrong,
|
|
paddingInline: "0.75rem",
|
|
paddingBlock: "0.5rem",
|
|
fontWeight: 500,
|
|
},
|
|
|
|
primaryButton: {
|
|
borderRadius: "0.25rem",
|
|
borderStyle: "none",
|
|
backgroundColor: colors.primary,
|
|
color: colors.primaryText,
|
|
paddingInline: "0.75rem",
|
|
paddingBlock: "0.375rem",
|
|
fontSize: "0.875rem",
|
|
lineHeight: "1.25rem",
|
|
fontWeight: 500,
|
|
opacity: { default: 1, [DISABLED]: 0.5 },
|
|
},
|
|
largePrimaryButton: {
|
|
borderRadius: "0.25rem",
|
|
borderStyle: "none",
|
|
backgroundColor: colors.primary,
|
|
color: colors.primaryText,
|
|
paddingInline: "0.75rem",
|
|
paddingBlock: "0.5rem",
|
|
fontWeight: 500,
|
|
opacity: { default: 1, [DISABLED]: 0.5 },
|
|
},
|
|
|
|
rowButton: {
|
|
borderRadius: "0.25rem",
|
|
borderStyle: "none",
|
|
backgroundColor: "transparent",
|
|
paddingInline: "0.5rem",
|
|
paddingBlock: "0.25rem",
|
|
fontSize: "0.875rem",
|
|
lineHeight: "1.25rem",
|
|
color: colors.primaryOnSurface,
|
|
},
|
|
linkButton: {
|
|
borderStyle: "none",
|
|
backgroundColor: "transparent",
|
|
padding: 0,
|
|
fontSize: "0.875rem",
|
|
lineHeight: "1.25rem",
|
|
fontWeight: 500,
|
|
color: colors.primaryOnSurface,
|
|
},
|
|
dangerLinkButton: {
|
|
borderStyle: "none",
|
|
backgroundColor: "transparent",
|
|
padding: 0,
|
|
fontSize: "0.875rem",
|
|
lineHeight: "1.25rem",
|
|
fontWeight: 500,
|
|
color: colors.danger,
|
|
opacity: { default: 1, [DISABLED]: 0.5 },
|
|
},
|
|
retryButton: {
|
|
marginTop: "0.75rem",
|
|
borderRadius: "0.25rem",
|
|
borderWidth: 1,
|
|
borderStyle: "solid",
|
|
borderColor: colors.dangerBorder,
|
|
backgroundColor: "transparent",
|
|
paddingInline: "0.75rem",
|
|
paddingBlock: "0.375rem",
|
|
fontSize: "0.875rem",
|
|
lineHeight: "1.25rem",
|
|
fontWeight: 500,
|
|
color: colors.dangerText,
|
|
},
|
|
|
|
/** Marks an element as waiting on data. Carries no colour of its own. */
|
|
pulse: {
|
|
animationName: pulseFrames,
|
|
animationDuration: "2s",
|
|
animationTimingFunction: "cubic-bezier(0.4, 0, 0.6, 1)",
|
|
animationIterationCount: "infinite",
|
|
},
|
|
/** Digits of equal width, so a column of counts does not jitter as it updates. */
|
|
tabularNums: {
|
|
fontVariantNumeric: "tabular-nums",
|
|
},
|
|
/**
|
|
* A learned name is runtime state, not something the operator typed, so it
|
|
* reads muted wherever it appears. The Clients page adds the outlined tag,
|
|
* where the client is named once; the query tables leave it off rather than
|
|
* repeat it on every row. The tag is real text — a screen reader announces
|
|
* it — because colour alone is not an affordance.
|
|
*/
|
|
learnedName: {
|
|
color: colors.textMuted,
|
|
},
|
|
learnedTag: {
|
|
marginLeft: "0.5rem",
|
|
borderWidth: 1,
|
|
borderStyle: "solid",
|
|
borderColor: colors.border,
|
|
borderRadius: "0.25rem",
|
|
paddingInline: "0.375rem",
|
|
paddingBlock: "0.125rem",
|
|
fontSize: "0.75rem",
|
|
lineHeight: "1rem",
|
|
color: colors.textMuted,
|
|
},
|
|
/** For a value the operator reads character by character: a domain, an IP, a URL. */
|
|
mono: {
|
|
fontFamily: "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",
|
|
},
|
|
/**
|
|
* Visible to a screen reader only; the element keeps its place in the a11y tree.
|
|
*
|
|
* Apply it to a block container. `overflow` has no effect on a table box, and
|
|
* `height` on one is a minimum, so a `<table>` wearing this still lays out at
|
|
* its full content height and pushes the page's scrollable overflow past the
|
|
* app shell — invisible, because `clip-path` still hides the paint. Wrap the
|
|
* table in a hidden `<div>` instead of hiding the table itself.
|
|
*/
|
|
srOnly: {
|
|
position: "absolute",
|
|
width: 1,
|
|
height: 1,
|
|
padding: 0,
|
|
margin: -1,
|
|
overflow: "hidden",
|
|
clipPath: "inset(50%)",
|
|
whiteSpace: "nowrap",
|
|
borderWidth: 0,
|
|
},
|
|
|
|
th: {
|
|
borderBottomWidth: 1,
|
|
borderBottomStyle: "solid",
|
|
borderBottomColor: colors.borderStrong,
|
|
paddingInline: "0.75rem",
|
|
paddingBlock: "0.5rem",
|
|
textAlign: "left",
|
|
fontWeight: 500,
|
|
},
|
|
td: {
|
|
borderBottomWidth: 1,
|
|
borderBottomStyle: "solid",
|
|
borderBottomColor: colors.border,
|
|
paddingInline: "0.75rem",
|
|
paddingBlock: "0.5rem",
|
|
},
|
|
tableWrap: {
|
|
marginTop: "1rem",
|
|
overflowX: "auto",
|
|
},
|
|
/**
|
|
* Not a faithful port: `space-y-3` set sibling margins on a block container,
|
|
* this is a flex formatting context. StyleX has no way to write the `> * + *`
|
|
* selector that `space-y` compiles to, so the rhythm can only come from
|
|
* `gap`. Child sizing and margin behaviour differ from the Tailwind original;
|
|
* both call sites are plain vertical form stacks, where they do not.
|
|
*/
|
|
formCard: {
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
gap: "0.75rem",
|
|
marginTop: "1rem",
|
|
maxWidth: "32rem",
|
|
borderRadius: "0.25rem",
|
|
borderWidth: 1,
|
|
borderStyle: "solid",
|
|
borderColor: colors.border,
|
|
padding: "1rem",
|
|
},
|
|
});
|