Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
"ci": "npm run test && npm run lint && npm run build && npx prettier --check src",
"deploy": "website-deploy-aws",
"panda": "panda codegen",
"dev:link-ui": "rm -rf node_modules/@microbit/ui && ln -s ../../../ui/packages/ui node_modules/@microbit/ui && rm -rf styled-system && npm run panda",
"dev:link-ui-patterns": "rm -rf node_modules/@microbit/ui-patterns && ln -s ../../../ui/packages/ui-patterns node_modules/@microbit/ui-patterns && rm -rf styled-system && npm run panda",
"dev:link-theme": "npm --prefix ../ml-trainer-microbit run build && mkdir -p node_modules/@microbit-foundation && rm -rf node_modules/@microbit-foundation/ml-trainer-microbit && ln -s ../../../ml-trainer-microbit node_modules/@microbit-foundation/ml-trainer-microbit && rm -rf styled-system && npm run panda",
"dev:unlink-theme": "rm -rf node_modules/@microbit-foundation/ml-trainer-microbit && rm -rf styled-system && npm run panda",
"predev": "npm run panda",
"dev": "cross-env VITE_VERSION=$npm_package_version vite",
"dev:apps": "cross-env VITE_BUILD_MODE=apps VITE_VERSION=$npm_package_version vite --host",
Expand Down
1 change: 1 addition & 0 deletions src/compliance/NativeConsentDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export const NativeConsentDialog = ({
<>
{" "}
<Link
color="fg.link"
href={privacyPolicyLink}
target="_blank"
rel="noopener noreferrer"
Expand Down
2 changes: 1 addition & 1 deletion src/components/AboutDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ const AboutDialog = ({ isOpen, onClose, finalFocusRef }: AboutDialogProps) => {
values={{
link: (chunks: ReactNode) => (
<Link
color="brand.600"
color="fg.link"
textDecoration="underline"
href="https://cctd.au.dk/"
target="_blank"
Expand Down
2 changes: 1 addition & 1 deletion src/components/ActionBar/ActionBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const ActionBar = ({
as="header"
gap={0}
{...darkSurface}
bg="statusBarBg"
bg="surface.statusBar"
css={{ "--inset-top": "env(safe-area-inset-top)" }}
{...rest}
>
Expand Down
4 changes: 2 additions & 2 deletions src/components/BrokenFirmwareDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const BrokenFirmwareDialog = ({
values={{
link: (chunks: ReactNode) => (
<Link
color="brand.600"
color="fg.link"
textDecoration="underline"
href="https://microbit.org/get-started/user-guide/firmware/"
target="_blank"
Expand All @@ -68,7 +68,7 @@ const BrokenFirmwareDialog = ({
</Text>
<Text w="100%">
<Link
color="brand.600"
color="fg.link"
textDecoration="underline"
href={supportLinks.troubleshooting}
target="_blank"
Expand Down
2 changes: 1 addition & 1 deletion src/components/ConnectBatteryDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const ConnectBatteryDialog = ({ ...props }: ConnectBatteryDialogProps) => {
<Text alignSelf="left" width="100%">
<FormattedMessage id="connect-battery-subtitle" />
<Link
color="brand.600"
color="fg.link"
textDecoration="underline"
href={supportLinks.wearable}
target="_blank"
Expand Down
6 changes: 1 addition & 5 deletions src/components/DownloadProgressDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,7 @@ const DownloadProgressDialog = ({
</ModalBody>
<ModalFooter css={{ justifyContent: "start" }}>
{isNativePlatform() && tryAgain && isFindingDevice && (
<Button
variant="link"
css={{ color: "brand.600" }}
onPress={tryAgain}
>
<Button variant="link" css={{ color: "fg.link" }} onPress={tryAgain}>
<FormattedMessage id="connect-native-change-pattern" />
</Button>
)}
Expand Down
2 changes: 1 addition & 1 deletion src/components/ErrorHandlerErrorView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const ErrorHandlerErrorView = ({ error }: ErrorHandlerErrorViewProps) => {
values={{
link: (chunks: ReactNode) => (
<Link
color="brand.600"
color="fg.link"
textDecoration="underline"
href="https://support.microbit.org"
target="_blank"
Expand Down
4 changes: 2 additions & 2 deletions src/components/IncompatibleEditorDevice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const IncompatibleEditorDevice = ({
values={{
link: (children) => (
<Link
color="brand.600"
color="fg.link"
textDecoration="underline"
href="https://support.microbit.org/support/solutions/articles/19000154234-which-version-of-micro-bit-do-i-have-"
target="_blank"
Expand All @@ -85,7 +85,7 @@ const IncompatibleEditorDevice = ({
<Button
variant="link"
css={{
color: "brand.600",
color: "fg.link",
textDecoration: "underline",
}}
onPress={() => saveHex(SaveType.Download)}
Expand Down
2 changes: 1 addition & 1 deletion src/components/NotFound.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const NotFound = ({ href }: NotFoundProps) => {
return (
<ErrorPage title={intl.formatMessage({ id: "not-found-title" })}>
<Link
color="brand.600"
color="fg.link"
textDecoration="underline"
href={href ? href : createHomePageUrl()}
>
Expand Down
4 changes: 2 additions & 2 deletions src/components/UnsupportedMicrobitDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const UnsupportedMicrobitDialog = ({
values={{
link: (chunks: ReactNode) => (
<Link
color="brand.600"
color="fg.link"
textDecoration="underline"
href="https://support.microbit.org/support/solutions/articles/19000119162"
target="_blank"
Expand All @@ -72,7 +72,7 @@ const UnsupportedMicrobitDialog = ({
values={{
link: (chunks: ReactNode) => (
<Link
color="brand.600"
color="fg.link"
textDecoration="underline"
href={supportLinks.bluetooth}
target="_blank"
Expand Down
54 changes: 54 additions & 0 deletions src/deployment/default/panda-preset.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* (c) 2026, Micro:bit Educational Foundation and contributors
*
* SPDX-License-Identifier: MIT
*/
import {
droppedConditionTokens,
unknownSemanticTokens,
} from "@microbit/ui/preset-lint";
import { createRequire } from "node:module";
import { describe, expect, it } from "vitest";
import { appPreset } from "./panda-preset";

// Panda accepts an unknown `semanticTokens` key silently — the override
// never applies and nothing fails, so a rename in @microbit/ui would leave
// this app on the library's colours with a green typecheck. See the
// CSS-variable contract in @microbit/ui's README.

it("app preset overrides only semantic tokens @microbit/ui defines", () => {
expect(unknownSemanticTokens(appPreset)).toEqual([]);
});

// A flat override of a { base, _onDark } token merges wholesale and
// silently drops the dark-surface flip — the same failure, one door over.
it("app preset keeps every condition the base preset's tokens carry", () => {
expect(droppedConditionTokens(appPreset)).toEqual([]);
});

// The private brand preset is optional — present only when linked
// (`npm run dev:link-theme`) or installed in a brand build, exactly as
// panda.config.ts treats it. Checked here rather than in its own repo so
// that repo stays free of a dependency on this library, and because the
// merge this guards against happens on this side.
const require = createRequire(import.meta.url);
let brandPreset: unknown;
try {
brandPreset = (
require("@microbit-foundation/ml-trainer-microbit/panda-preset") as {
default: unknown;
}
).default;
} catch {
brandPreset = undefined;
}

describe.skipIf(!brandPreset)("private brand preset", () => {
it("overrides only semantic tokens @microbit/ui defines", () => {
expect(unknownSemanticTokens(brandPreset)).toEqual([]);
});

it("keeps every condition the base preset's tokens carry", () => {
expect(droppedConditionTokens(brandPreset)).toEqual([]);
});
});
6 changes: 3 additions & 3 deletions src/deployment/default/panda-preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ export const appPreset = definePreset({
// The native app's status-bar area (the ActionBar and the
// full-screen dialog's safe-area gradient) follows the second
// accent.
statusBarBg: { value: "{colors.brand2.500}" },
surface: { statusBar: { value: "{colors.brand2.500}" } },
},
},
// This app's button vocabulary, merged into the core `button` recipe.
Expand Down Expand Up @@ -309,8 +309,8 @@ export const appPreset = definePreset({
// pressed. Same tokens as `secondary` so the two can't drift.
"secondary-disabled": {
borderWidth: "2px",
borderColor: "button.secondaryBorder",
color: "button.secondaryText",
borderColor: "button.secondary.border",
color: "button.secondary.fg",
bg: "transparent",
opacity: "0.4",
},
Expand Down
2 changes: 1 addition & 1 deletion src/pages/OpenSharedProjectPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ const OpenSharedProjectPage = () => {
values={{
link: (children: ReactNode) => (
<Link
color="brand.600"
color="fg.link"
textDecoration="underline"
href={`https://makecode.microbit.org/${encodeURIComponent(
shareId!
Expand Down
Loading