diff --git a/.changeset/tame-bugs-relax.md b/.changeset/tame-bugs-relax.md
new file mode 100644
index 00000000..1416b860
--- /dev/null
+++ b/.changeset/tame-bugs-relax.md
@@ -0,0 +1,5 @@
+---
+'scoobie': major
+---
+
+styles: Remove submodule export
diff --git a/.changeset/ten-cups-eat.md b/.changeset/ten-cups-eat.md
new file mode 100644
index 00000000..9235fb29
--- /dev/null
+++ b/.changeset/ten-cups-eat.md
@@ -0,0 +1,5 @@
+---
+'scoobie': minor
+---
+
+CodeBlock, CodeContainer, CodeThemeProvider: Add `scoobieDark` and `scoobieLight` themes
diff --git a/.loki/reference/chrome_laptop_Standalone_CodeThemeProvider_Scoobie_Dark.png b/.loki/reference/chrome_laptop_Standalone_CodeThemeProvider_Scoobie_Dark.png
new file mode 100644
index 00000000..8024671f
--- /dev/null
+++ b/.loki/reference/chrome_laptop_Standalone_CodeThemeProvider_Scoobie_Dark.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a5e98a888a052ea0339e3a0b0dd54650558baa0b8d3b4e8e8d49dbaebcd080d7
+size 818935
diff --git a/.loki/reference/chrome_laptop_Standalone_CodeThemeProvider_Scoobie_Light.png b/.loki/reference/chrome_laptop_Standalone_CodeThemeProvider_Scoobie_Light.png
new file mode 100644
index 00000000..7bab2cae
--- /dev/null
+++ b/.loki/reference/chrome_laptop_Standalone_CodeThemeProvider_Scoobie_Light.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4fffe767a3a5961df0531d6c8c833df7b49c90185004616ad5e08c0e6cf15867
+size 833240
diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx
index d9546aaf..916ca79e 100644
--- a/.storybook/preview.tsx
+++ b/.storybook/preview.tsx
@@ -5,13 +5,12 @@ import { BraidProvider, Card, PageBlock } from 'braid-design-system';
import docs from 'braid-design-system/themes/docs';
import seekJobs from 'braid-design-system/themes/seekJobs';
import wireframe from 'braid-design-system/themes/wireframe';
-import { themes } from 'prism-react-renderer';
-import React from 'react';
import { Helmet, HelmetProvider } from 'react-helmet-async';
import { BrowserRouter } from 'react-router-dom';
import { CodeThemeProvider } from '../src/components/CodeThemeProvider';
import { ScoobieLink } from '../src/components/ScoobieLink';
+import { codeThemes } from '../src/private/codeThemes';
import { robotoHref, robotoMonoHref } from '../typography';
const THEMES = { docs, seekJobs, wireframe };
@@ -20,13 +19,22 @@ export type BraidThemeName = 'docs' | 'seekJobs' | 'wireframe';
export default {
globalTypes: {
+ colorMode: {
+ description: 'Color mode to use',
+ defaultValue: 'lightMode',
+ toolbar: {
+ title: 'Color mode',
+ icon: 'contrast',
+ items: ['darkMode', 'lightMode'],
+ },
+ },
codeTheme: {
description: 'Code theme to use',
defaultValue: 'github',
toolbar: {
title: 'Code theme',
icon: 'contrast',
- items: Object.keys(themes),
+ items: Object.keys(codeThemes),
},
},
theme: {
@@ -40,27 +48,37 @@ export default {
},
},
decorators: [
- (Story, { globals }) => (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ),
+ (Story, { globals }) => {
+ const DARK_MODE_CLASS = 'sprinkles_darkMode__1t46ksg10';
+
+ if (globals.colorMode === 'darkMode') {
+ document.documentElement.classList.add(DARK_MODE_CLASS);
+ } else {
+ document.documentElement.classList.remove(DARK_MODE_CLASS);
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ },
],
} satisfies Preview;
diff --git a/README.md b/README.md
index cc7a7c0a..e8b976c3 100644
--- a/README.md
+++ b/README.md
@@ -234,39 +234,6 @@ export const SomeLinks = () => (
);
```
-## Styling reference
-
-Scoobie distributes some vanilla-extract styles via `scoobie/styles` submodules.
-
-### code
-
-Render text with the same monospace styling as our [CodeBlock](#codeblock):
-
-```tsx
-import { Box } from 'braid-design-system';
-import React from 'react';
-import { code } from 'scoobie/styles/code.css';
-
-export const MyBox = () => (
-
- Hello
-
-);
-```
-
-### img
-
-```tsx
-import React from 'react';
-import { img } from 'scoobie/styles/img.css';
-
-export const MySvg = () => (
-
-);
-```
-
## Webpack reference
Scoobie distributes its Webpack config via a `scoobie/webpack` submodule:
diff --git a/package.json b/package.json
index ad32fe34..37cabd63 100644
--- a/package.json
+++ b/package.json
@@ -36,7 +36,6 @@
},
"files": [
"src",
- "styles",
"webpack",
"types.d.ts",
"typography.ts"
diff --git a/sku.config.ts b/sku.config.ts
index 0f8dde7f..15ebadfd 100644
--- a/sku.config.ts
+++ b/sku.config.ts
@@ -2,7 +2,7 @@ import type { SkuConfig } from 'sku';
const config: SkuConfig = {
rootResolution: false,
- srcPaths: ['./src', './styles'],
+ srcPaths: ['./src'],
dangerouslySetESLintConfig: (skuConfig) => [
...skuConfig,
diff --git a/src/components/CodeContainer.css.ts b/src/components/CodeContainer.css.ts
index 08f07e8e..189316b4 100644
--- a/src/components/CodeContainer.css.ts
+++ b/src/components/CodeContainer.css.ts
@@ -3,7 +3,7 @@ import { calc } from '@vanilla-extract/css-utils';
import { colorModeStyle, responsiveStyle, vars } from 'braid-design-system/css';
import { darken, lighten } from 'polished';
-import { codeBackgroundColor } from '../../styles';
+import { codeBackgroundColor } from '../private/color';
export const lineNumberContainer = style([
{
diff --git a/src/components/CodeContainer.tsx b/src/components/CodeContainer.tsx
index 45dc72c0..082d380e 100644
--- a/src/components/CodeContainer.tsx
+++ b/src/components/CodeContainer.tsx
@@ -1,12 +1,13 @@
import { Box, Stack } from 'braid-design-system';
import { Highlight, type Token } from 'prism-react-renderer';
-import { Prism, themes } from '../private/Prism';
+import { Prism } from '../private/Prism';
+import { codeThemes } from '../private/codeThemes';
import { useCodeTheme } from './CodeThemeProvider';
import * as styles from './CodeContainer.css';
-import * as codeStyles from '../../styles/code.css';
+import * as fontStyles from '../private/font.css';
export const CodeContainer = ({
code,
@@ -25,7 +26,7 @@ export const CodeContainer = ({
prism={Prism}
code={code}
language={language}
- theme={themes[theme]}
+ theme={codeThemes[theme]}
>
{({ getTokenProps, tokens }) => (
@@ -46,7 +47,7 @@ const LineNumbers = ({ count }: { count: number }) => {
{numbers.map((number) => (
-
+
{number}
))}
@@ -69,7 +70,7 @@ const Lines = ({
{lines.map((line, lineIndex) => (
-
+
{line.map((token, tokenIndex) => {
const props = getTokenProps({ token });
diff --git a/src/components/CodeThemeProvider.stories.tsx b/src/components/CodeThemeProvider.stories.tsx
new file mode 100644
index 00000000..ab3612f6
--- /dev/null
+++ b/src/components/CodeThemeProvider.stories.tsx
@@ -0,0 +1,521 @@
+import 'loki/configure-react';
+
+import type { Meta, StoryObj } from '@storybook/react';
+import { Stack } from 'braid-design-system';
+
+import { codeThemes } from '../private/codeThemes';
+
+import { CodeContainer } from './CodeContainer';
+import { CodeThemeProvider as Component } from './CodeThemeProvider';
+
+const codeSamples = [
+ {
+ language: 'diff',
+ code: `
+- Removed line
++ Inserted line
+`,
+ },
+ {
+ language: 'graphql',
+ code: `
+# Inline arguments are only used to simplify these examples.
+# Parameterise your production queries as per advice above.
+
+# Correct: omit unused argument
+query Omit {
+ events(schemeId: "seekAnzPublicTest") {
+ pageInfo {
+ hasNextPage
+ }
+ }
+}
+
+# Incorrect: set unused argument to null
+query Null {
+ events(schemeId: "seekAnzPublicTest", after: null) {
+ pageInfo {
+ hasNextPage
+ }
+ }
+}
+
+# Incorrect: set unused argument to an empty string
+query EmptyString {
+ events(schemeId: "seekAnzPublicTest", after: "") {
+ pageInfo {
+ hasNextPage
+ }
+ }
+}
+
+# Incorrect: create variable for unused argument
+query Variable($after: String!) {
+ events(schemeId: "seekAnzPublicTest", after: $after) {
+ pageInfo {
+ hasNextPage
+ }
+ }
+}
+`,
+ },
+ {
+ language: 'http',
+ code: `
+POST https://graphql.seek.com/graphql HTTP/1.1
+
+Accept-Language: en-AU
+
+Authorization: Bearer PARTNER_TOKEN_HERE
+
+Content-Type: application/json
+
+User-Agent: example-application/1.2.3
+
+X-Request-Id: a9e3d78d-576d-470b-b1d2-52f4921be25c
+
+X-Session-Id: b5a8774c-c450-4906-a25c-861bce129106
+
+{
+
+ "query": "{ version }"
+
+}
+`,
+ },
+ {
+ language: 'json',
+ code: `
+{
+ "hiringOrganization": {
+ "name": "Acme Corp"
+ }
+}
+`,
+ },
+ {
+ language: 'bash',
+ code: `
+#!/bin/sh
+
+# In practice, propagate language preferences from the end-user client.
+# https://developer.seek.com/graphql/in-practice#content-localisation
+acceptLanguage='en-AU'
+
+# In practice, retrieve and cache an access token dynamically at runtime.
+# https://developer.seek.com/auth
+accessToken=''
+
+# In practice, use your application name and version from configuration.
+# https://developer.seek.com/graphql/in-practice#tracing-requests
+userAgent='example-application/1.2.3'
+
+# In practice, share the session ID among requests in a given interaction.
+# https://developer.seek.com/graphql/in-practice#tracing-requests
+sessionId="$(uuidgen)"
+
+# In practice, be wary of code injection.
+# https://developer.seek.com/graphql/in-practice#variables
+data='{"query": "{ version }"}'
+
+# In practice, use a GraphQL client and something other than a Bash script.
+# https://developer.seek.com/graphql/in-practice#client-libraries-and-tools
+# https://graphql.org/community/tools-and-libraries/?tags=client
+response="$(
+ curl \
+ --data "\${data}" \
+ --header "Accept-Language: \${acceptLanguage}" \
+ --header "Authorization: Bearer \${accessToken}" \
+ --header 'Content-Type: application/json' \
+ --header "User-Agent: \${userAgent}" \
+ --header "X-Request-Id: $(uuidgen)" \
+ --header "X-Session-Id: \${sessionId}" \
+ --request POST \
+ --silent \
+ --write-out '\n%{http_code}' \
+ 'https://graphql.seek.com/graphql'
+)"
+
+echo "\${response}" | tail -n 1
+# 200
+
+echo "\${response}" | head -n 1
+# {"data":{"version":"abcdefa.12345"},"extensions":{"requestLatency":1}}
+`,
+ },
+ {
+ language: 'csharp',
+ code: `
+using System.Net.Http.Headers;
+using System.Text;
+
+class Program
+{
+ static async Task Main()
+ {
+ // In practice, propagate language preferences from the end-user client.
+ // https://developer.seek.com/graphql/in-practice#content-localisation
+ var acceptLanguage = "en-AU";
+
+ // In practice, retrieve and cache an access token dynamically at runtime.
+ // https://developer.seek.com/auth
+ var accessToken = "";
+
+ // In practice, use your application name and version from configuration.
+ // https://developer.seek.com/graphql/in-practice#tracing-requests
+ var userAgent = "example-application/1.2.3";
+
+ // In practice, share the session ID among requests in a given interaction.
+ // https://developer.seek.com/graphql/in-practice#tracing-requests
+ var sessionId = Guid.NewGuid().ToString(); // V4 UUID
+
+ // In practice, use a GraphQL client.
+ // https://developer.seek.com/graphql/in-practice#client-libraries-and-tools
+ // https://graphql.org/community/tools-and-libraries/?tags=client_c-net
+ using (var httpClient = new HttpClient())
+ {
+ var request = new HttpRequestMessage(HttpMethod.Post, "https://graphql.seek.com/graphql");
+ request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(acceptLanguage));
+ request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
+ request.Headers.UserAgent.ParseAdd(userAgent);
+ request.Headers.Add("X-Request-Id", Guid.NewGuid().ToString());
+ request.Headers.Add("X-Session-Id", sessionId);
+ // In practice, be wary of code injection.
+ // https://developer.seek.com/graphql/in-practice#variables
+ request.Content = new StringContent("{\"query\": \"{ version }\"}", Encoding.UTF8, "application/json");
+
+ var response = await httpClient.SendAsync(request);
+ var responseBody = await response.Content.ReadAsStringAsync();
+
+ Console.WriteLine((int)response.StatusCode);
+ // 200
+
+ Console.WriteLine(responseBody);
+ // {"data":{"version":"abcdefa.12345"},"extensions":{"requestLatency":1}}
+ }
+ }
+}
+`,
+ },
+ {
+ language: 'java',
+ code: `
+import java.io.IOException;
+import java.lang.InterruptedException;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.UUID;
+
+class Main {
+ public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
+ // In practice, propagate language preferences from the end-user client.
+ // https://developer.seek.com/graphql/in-practice#content-localisation
+ var acceptLanguage = "en-AU";
+
+ // In practice, retrieve and cache an access token dynamically at runtime.
+ // https://developer.seek.com/auth
+ var accessToken = "";
+
+ // In practice, use your application name and version from configuration.
+ // https://developer.seek.com/graphql/in-practice#tracing-requests
+ var userAgent = "example-application/1.2.3";
+
+ // In practice, share the session ID among requests in a given interaction.
+ // https://developer.seek.com/graphql/in-practice#tracing-requests
+ var sessionId = UUID.randomUUID();
+
+ // In practice, use a GraphQL client.
+ // https://developer.seek.com/graphql/in-practice#client-libraries-and-tools
+ // https://graphql.org/community/tools-and-libraries/?tags=client_java-kotlin-android
+ var client = HttpClient.newHttpClient();
+
+ var request = HttpRequest.newBuilder()
+ .uri(new URI("https://graphql.seek.com/graphql"))
+ .header("Accept-Language", acceptLanguage)
+ .header("Authorization", "Bearer " + accessToken)
+ .header("Content-Type", "application/json")
+ .header("User-Agent", userAgent)
+ .header("X-Request-Id", UUID.randomUUID().toString())
+ .header("X-Session-Id", sessionId.toString())
+ // In practice, be wary of code injection.
+ // https://developer.seek.com/graphql/in-practice#variables
+ .POST(HttpRequest.BodyPublishers.ofString("{\"query\": \"{ version }\"}"))
+ .build();
+
+ // In practice, use \`sendAsync()\`.
+ var response = client
+ .send(request, HttpResponse.BodyHandlers.ofString());
+
+ System.out.println(response.statusCode());
+ // 200
+
+ System.out.println(response.body());
+ // {"data":{"version":"abcdefa.12345"},"extensions":{"requestLatency":1}}
+ }
+}
+`,
+ },
+ {
+ language: 'javascript',
+ code: `
+import { randomUUID } from 'node:crypto';
+
+const a = (a, b) => a + b;
+
+// In practice, propagate language preferences from the end-user client.
+// https://developer.seek.com/graphql/in-practice#content-localisation
+const acceptLanguage = 'en-AU';
+
+// In practice, retrieve and cache an access token dynamically at runtime.
+// https://developer.seek.com/auth
+const accessToken = '';
+
+// In practice, use your application name and version from configuration.
+// https://developer.seek.com/graphql/in-practice#tracing-requests
+const userAgent = 'example-application/1.2.3';
+
+// In practice, share the session ID among requests in a given interaction.
+// https://developer.seek.com/graphql/in-practice#tracing-requests
+const sessionId = randomUUID();
+
+// In practice, use a GraphQL client.
+// https://developer.seek.com/graphql/in-practice#client-libraries-and-tools
+// https://graphql.org/community/tools-and-libraries/?tags=client_javascript
+const response = await fetch('https://graphql.seek.com/graphql', {
+ // In practice, be wary of code injection.
+ // https://developer.seek.com/graphql/in-practice#variables
+ body: JSON.stringify({ query: '{ version }' }),
+ headers: {
+ 'Accept-Language': acceptLanguage,
+ Authorization: \`Bearer \${accessToken}\`,
+ 'Content-Type': 'application/json',
+ 'User-Agent': userAgent,
+ 'X-Request-Id': randomUUID(),
+ 'X-Session-Id': sessionId
+ },
+ method: 'POST'
+});
+
+// In practice, use \`json()\`.
+const responseBody = await response.text();
+
+console.log(response.status);
+// 200
+
+console.log(responseBody);
+// {"data":{"version":"abcdefa.12345"},"extensions":{"requestLatency":1}}
+`,
+ },
+ {
+ language: 'kotlin',
+ code: `
+import java.net.HttpURLConnection
+import java.net.URL
+import java.util.UUID
+
+fun main() {
+ // In practice, propagate language preferences from the end-user client.
+ // https://developer.seek.com/graphql/in-practice#content-localisation
+ val acceptLanguage = "en-AU"
+
+ // In practice, retrieve and cache an access token dynamically at runtime.
+ // https://developer.seek.com/auth
+ val accessToken = ""
+
+ // In practice, use your application name and version from configuration.
+ // https://developer.seek.com/graphql/in-practice#tracing-requests
+ val userAgent = "example-application/1.2.3"
+
+ // In practice, share the session ID among requests in a given interaction.
+ // https://developer.seek.com/graphql/in-practice#tracing-requests
+ val sessionId = UUID.randomUUID().toString()
+
+ // In practice, use a GraphQL client.
+ // https://developer.seek.com/graphql/in-practice#client-libraries-and-tools
+ // https://graphql.org/community/tools-and-libraries/?tags=client_java-kotlin-android
+ val url = URL("https://graphql.seek.com/graphql")
+ val connection = url.openConnection() as HttpURLConnection
+ connection.setRequestMethod("POST")
+ connection.setRequestProperty("Accept-Language", acceptLanguage)
+ connection.setRequestProperty("Authorization", "Bearer $accessToken")
+ connection.setRequestProperty("Content-Type", "application/json")
+ connection.setRequestProperty("User-Agent", userAgent)
+ connection.setRequestProperty("X-Request-Id", UUID.randomUUID().toString())
+ connection.setRequestProperty("X-Session-Id", sessionId)
+ connection.setDoOutput(true)
+ // In practice, be wary of code injection.
+ // https://developer.seek.com/graphql/in-practice#variables
+ connection.outputStream.use { it.write("{\"query\":\"{ version }\"}".toByteArray())}
+
+ val responseBody = connection.inputStream.bufferedReader().use { it.readText() }
+
+ println(connection.responseCode)
+ // 200
+
+ println(responseBody)
+ // {"data":{"version":"abcdefa.12345"},"extensions":{"requestLatency":1}}
+}
+ `,
+ },
+ {
+ language: 'python',
+ code: `
+import json
+import urllib.request
+import urllib.parse
+import uuid
+
+# In practice, propagate language preferences from the end-user client.
+# https://developer.seek.com/graphql/in-practice#content-localisation
+accept_language = 'en-AU'
+
+# In practice, retrieve and cache an access token dynamically at runtime.
+# https://developer.seek.com/auth
+access_token = ''
+
+# In practice, use your application name and version from configuration.
+# https://developer.seek.com/graphql/in-practice#tracing-requests
+user_agent = 'example-application/1.2.3'
+
+# In practice, share the session ID among requests in a given interaction.
+# https://developer.seek.com/graphql/in-practice#tracing-requests
+session_id = str(uuid.uuid4())
+
+# In practice, use a GraphQL client.
+# https://developer.seek.com/graphql/in-practice#client-libraries-and-tools
+# https://graphql.org/community/tools-and-libraries/?tags=client_python
+url = 'https://graphql.seek.com/graphql'
+headers = {
+ 'Accept-Language': accept_language,
+ 'Authorization': f'Bearer {access_token}',
+ 'Content-Type': 'application/json',
+ 'User-Agent': user_agent,
+ 'X-Request-Id': str(uuid.uuid4()),
+ 'X-Session-Id': session_id
+}
+# In practice, be wary of code injection.
+# https://developer.seek.com/graphql/in-practice#variables
+data = json.dumps({
+ 'query': '{ version }'
+}).encode('utf-8')
+request = urllib.request.Request(url, data, headers)
+
+with urllib.request.urlopen(request) as response:
+ response_body = response.read().decode('utf-8')
+
+print(response.status)
+# 200
+
+print(response_body)
+# {"data":{"version":"abcdefa.12345"},"extensions":{"requestLatency":1}}
+ `,
+ },
+ {
+ language: 'swift',
+ code: `
+import Foundation
+import FoundationNetworking
+
+// In practice, propagate language preferences from the end-user client.
+// https://developer.seek.com/graphql/in-practice#content-localisation
+let acceptLanguage = "en-AU"
+
+// In practice, retrieve and cache an access token dynamically at runtime.
+// https://developer.seek.com/auth
+let accessToken = ""
+
+// In practice, use your application name and version from configuration.
+// https://developer.seek.com/graphql/in-practice#tracing-requests
+let userAgent = "example-application/1.2.3"
+
+// In practice, share the session ID among requests in a given interaction.
+// https://developer.seek.com/graphql/in-practice#tracing-requests
+let sessionId = UUID().uuidString
+
+// In practice, use a GraphQL client.
+// https://developer.seek.com/graphql/in-practice#client-libraries-and-tools
+// https://graphql.org/community/tools-and-libraries/?tags=client_swift-objective-c-ios
+let url = URL(string: "https://graphql.seek.com/graphql")!
+var request = URLRequest(url: url)
+request.httpMethod = "POST"
+request.addValue(acceptLanguage, forHTTPHeaderField: "Accept-Language")
+request.addValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
+request.addValue("application/json", forHTTPHeaderField: "Content-Type")
+request.addValue(userAgent, forHTTPHeaderField: "User-Agent")
+request.addValue(UUID().uuidString, forHTTPHeaderField: "X-Request-Id")
+request.addValue(sessionId, forHTTPHeaderField: "X-Session-Id")
+// In practice, be wary of code injection.
+// https://developer.seek.com/graphql/in-practice#variables
+request.httpBody = try JSONSerialization.data(withJSONObject: ["query": "{ version }"])
+
+// In practice, properly handle concurrency and errors.
+let semaphore = DispatchSemaphore(value: 0)
+
+let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
+ print((response as! HTTPURLResponse).statusCode)
+ // 200
+
+ print(String(data: data!, encoding: .utf8)!)
+ // {"data":{"version":"abcdefa.12345"},"extensions":{"requestLatency":1}}
+
+ semaphore.signal()
+}
+
+task.resume()
+
+semaphore.wait()
+ `,
+ },
+];
+
+export default {
+ title: 'Standalone/CodeThemeProvider',
+ component: Component,
+ argTypes: {
+ theme: {
+ control: { type: 'select' },
+ options: Object.keys(codeThemes),
+ },
+ },
+} satisfies Meta;
+
+type Story = StoryObj;
+
+const children = (
+
+ {codeSamples.map((sample) => (
+
+ ))}
+
+);
+
+export const ScoobieDark: Story = {
+ globals: {
+ colorMode: 'darkMode',
+ },
+ args: {
+ children,
+ theme: 'scoobieDark',
+ },
+ parameters: {
+ loki: { skip: true },
+ },
+};
+
+export const ScoobieLight: Story = {
+ globals: {
+ colorMode: 'lightMode',
+ },
+ args: {
+ children,
+ theme: 'scoobieLight',
+ },
+};
diff --git a/src/components/CodeThemeProvider.tsx b/src/components/CodeThemeProvider.tsx
index 94290703..f2952c10 100644
--- a/src/components/CodeThemeProvider.tsx
+++ b/src/components/CodeThemeProvider.tsx
@@ -1,17 +1,16 @@
-import type { themes } from 'prism-react-renderer';
import { type ReactNode, createContext, useContext } from 'react';
-type CodeTheme = keyof typeof themes;
+import type { CodeTheme } from '../private/codeThemes';
-const ctx = createContext('github');
+const ctx = createContext('scoobieLight');
interface CodeThemeProviderProps {
children: ReactNode;
/**
- * The current color mode.
+ * The current code theme.
*
- * This defaults to `lightMode` in the absence of a `ColorModeProvider`.
+ * This defaults to `scoobieLight` in the absence of a `CodeThemeProvider`.
*/
theme: CodeTheme;
}
diff --git a/src/components/InlineCode.css.ts b/src/components/InlineCode.css.ts
index 443d4ab5..e204b6e0 100644
--- a/src/components/InlineCode.css.ts
+++ b/src/components/InlineCode.css.ts
@@ -3,7 +3,9 @@ import { calc } from '@vanilla-extract/css-utils';
import { colorModeStyle, vars } from 'braid-design-system/css';
import { darken, lighten } from 'polished';
-import { codeBackgroundColor, monospaceFontFamily } from '../../styles';
+import { codeBackgroundColor } from '../private/color';
+
+import { monospaceFontFamily } from '../private/font.css';
export const base = style({
fontFamily: monospaceFontFamily,
diff --git a/src/private/codeThemes.ts b/src/private/codeThemes.ts
new file mode 100644
index 00000000..2f39a026
--- /dev/null
+++ b/src/private/codeThemes.ts
@@ -0,0 +1,139 @@
+import { type PrismTheme, themes } from 'prism-react-renderer';
+
+import { palette } from './color';
+
+export type CodeTheme = keyof typeof codeThemes;
+
+export const codeThemes = {
+ ...themes,
+ scoobieLight: {
+ plain: {
+ color: palette.grey[700],
+ },
+ styles: [
+ {
+ types: [
+ 'class-name',
+ 'entity',
+ 'url',
+ 'symbol',
+ 'number',
+ 'boolean',
+ 'variable',
+ 'constant',
+ 'regex',
+ ],
+ style: {
+ color: palette.cyan[700],
+ },
+ },
+ {
+ types: ['comment', 'prolog', 'doctype', 'cdata', 'inserted'],
+ style: {
+ color: palette.mint[700],
+ },
+ },
+ {
+ types: ['comment', 'prolog', 'doctype', 'cdata'],
+ style: {
+ fontStyle: 'italic',
+ },
+ },
+ {
+ types: ['namespace'],
+ style: {
+ color: palette.grey[500],
+ },
+ },
+ {
+ types: ['string', 'attr-value'],
+ style: {
+ color: palette.orange[700],
+ },
+ },
+ {
+ types: ['atrule', 'keyword', 'attr-name', 'selector'],
+ style: {
+ color: palette.blue[600],
+ },
+ },
+ {
+ types: ['function', 'deleted', 'tag'],
+ style: {
+ color: palette.red[700],
+ },
+ },
+ {
+ types: ['tag', 'selector', 'keyword'],
+ style: {
+ color: palette.indigo[700],
+ },
+ },
+ ],
+ },
+ scoobieDark: {
+ plain: {
+ color: '#fff',
+ },
+ styles: [
+ {
+ types: [
+ 'class-name',
+ 'entity',
+ 'url',
+ 'symbol',
+ 'number',
+ 'boolean',
+ 'variable',
+ 'constant',
+ 'regex',
+ ],
+ style: {
+ color: palette.cyan[400],
+ },
+ },
+ {
+ types: ['comment', 'prolog', 'doctype', 'cdata', 'inserted'],
+ style: {
+ color: palette.mint[500],
+ },
+ },
+ {
+ types: ['comment', 'prolog', 'doctype', 'cdata'],
+ style: {
+ fontStyle: 'italic',
+ },
+ },
+ {
+ types: ['namespace'],
+ style: {
+ color: palette.grey[200],
+ },
+ },
+ {
+ types: ['string', 'attr-value'],
+ style: {
+ color: palette.orange[400],
+ },
+ },
+ {
+ types: ['atrule', 'keyword', 'attr-name', 'selector'],
+ style: {
+ color: palette.blue[400],
+ },
+ },
+ {
+ types: ['function', 'deleted', 'tag'],
+ style: {
+ color: palette.red[300],
+ },
+ },
+ {
+ types: ['tag', 'selector', 'keyword'],
+ style: {
+ color: palette.indigo[300],
+ },
+ },
+ ],
+ },
+} satisfies Record;
diff --git a/src/private/color.ts b/src/private/color.ts
new file mode 100644
index 00000000..c39bedf3
--- /dev/null
+++ b/src/private/color.ts
@@ -0,0 +1,180 @@
+// https://github.com/seek-oss/braid-design-system/blob/braid-design-system%4033.6.0/packages/braid-design-system/src/lib/color/palette.ts
+export const palette = {
+ grey: {
+ 900: '#0E131B',
+ 800: '#1C2330',
+ 700: '#2E3849',
+ 600: '#414C63',
+ 500: '#5A6881',
+ 400: '#838FA5',
+ 300: '#ABB3C1',
+ 200: '#D2D7DF',
+ 100: '#EAECF1',
+ 75: '#F3F5F7',
+ 50: '#F7F8FB',
+ },
+ seekPink: {
+ 900: '#520018',
+ 800: '#76002C',
+ 700: '#A00043',
+ 600: '#C6005B',
+ 500: '#E60278',
+ 400: '#EE399E',
+ 300: '#F470BD',
+ 200: '#F8B1DC',
+ 100: '#FCD9EF',
+ 50: '#FEEFFA',
+ },
+ seekBlue: {
+ 900: '#00061B',
+ 800: '#020F30',
+ 700: '#051A49',
+ 600: '#072462',
+ 500: '#0D3880',
+ 400: '#4166A4',
+ 300: '#7795C2',
+ 200: '#B6C7E0',
+ 100: '#DCE5F2',
+ 50: '#F0F6FC',
+ },
+ seekBlueLight: {
+ 900: '#081C60',
+ 800: '#122F83',
+ 700: '#1E47A9',
+ 600: '#2A60CD',
+ 500: '#4B84E7',
+ 400: '#6AA1F3',
+ 300: '#99BFF7',
+ 200: '#C9DEFA',
+ 100: '#E5F0FD',
+ 50: '#F0F7FE',
+ },
+ red: {
+ 900: '#750606',
+ 800: '#941110',
+ 700: '#B91E1E',
+ 600: '#DC2C2D',
+ 500: '#F94344',
+ 400: '#FA6D6C',
+ 300: '#FB999A',
+ 200: '#FDC8C8',
+ 100: '#FFE3E2',
+ 50: '#FEF3F3',
+ },
+ orange: {
+ 900: '#751704',
+ 800: '#95290C',
+ 700: '#BB4116',
+ 600: '#E05821',
+ 500: '#FD7532',
+ 400: '#FD9C60',
+ 300: '#FEBB90',
+ 200: '#FEDAC2',
+ 100: '#FEEEE1',
+ 50: '#FEF9F2',
+ },
+ yellow: {
+ 900: '#723D02',
+ 800: '#945B07',
+ 700: '#B9800D',
+ 600: '#DFA414',
+ 500: '#FDC221',
+ 400: '#FDD651',
+ 300: '#FEE384',
+ 200: '#FEF0BC',
+ 100: '#FEF8DE',
+ 50: '#FEFDF1',
+ },
+ green: {
+ 900: '#073408',
+ 800: '#125113',
+ 700: '#1E771D',
+ 600: '#289927',
+ 500: '#3EB73D',
+ 400: '#6ACF6A',
+ 300: '#98DE97',
+ 200: '#C8EDC8',
+ 100: '#E3F7E3',
+ 50: '#F4FDF4',
+ },
+ mint: {
+ 900: '#043820',
+ 800: '#0A5435',
+ 700: '#12784F',
+ 600: '#199969',
+ 500: '#28B888',
+ 400: '#59CFA9',
+ 300: '#8BDEC5',
+ 200: '#C1EDE1',
+ 100: '#E2F7F1',
+ 50: '#F3FDFB',
+ },
+ cyan: {
+ 900: '#053842',
+ 800: '#095863',
+ 700: '#137D8B',
+ 600: '#19A1AF',
+ 500: '#28BFCE',
+ 400: '#56D3DF',
+ 300: '#88E2E9',
+ 200: '#BEEFF3',
+ 100: '#E1F8FA',
+ 50: '#F2FDFD',
+ },
+ blue: {
+ 900: '#072254',
+ 800: '#123976',
+ 700: '#1D559D',
+ 600: '#2A71C1',
+ 500: '#3E8FE0',
+ 400: '#6AB0EA',
+ 300: '#98C9F1',
+ 200: '#C8E1F7',
+ 100: '#E3F2FB',
+ 50: '#F4FBFE',
+ },
+ indigo: {
+ 900: '#08105F',
+ 800: '#152081',
+ 700: '#2433A7',
+ 600: '#3148C9',
+ 500: '#4964E9',
+ 400: '#748CF0',
+ 300: '#9FB0F5',
+ 200: '#CBD5F9',
+ 100: '#E6EAFC',
+ 50: '#F4F6FE',
+ },
+ violet: {
+ 900: '#120C64',
+ 800: '#241A83',
+ 700: '#392BA7',
+ 600: '#503DC9',
+ 500: '#6E56E6',
+ 400: '#937FEF',
+ 300: '#B5A7F4',
+ 200: '#D8D0FA',
+ 100: '#ECE9FC',
+ 50: '#F8F6FE',
+ },
+ purple: {
+ 900: '#3E0F65',
+ 800: '#5B2084',
+ 700: '#7F35A9',
+ 600: '#A04BCB',
+ 500: '#BE68E8',
+ 400: '#D48EF1',
+ 300: '#E1B2F5',
+ 200: '#F0D6FA',
+ 100: '#F9EBFD',
+ 50: '#FDF7FE',
+ },
+} as const;
+
+export const codeBackgroundColor = {
+ // Braid grey.50
+ lightMode: palette.grey[50],
+
+ // Braid grey.900
+ darkMode: palette.grey[900],
+};
diff --git a/styles/code.css.ts b/src/private/font.css.ts
similarity index 90%
rename from styles/code.css.ts
rename to src/private/font.css.ts
index d733c549..ba629660 100644
--- a/styles/code.css.ts
+++ b/src/private/font.css.ts
@@ -2,7 +2,9 @@ import { createStyleObject, getCapHeight } from '@capsizecss/core';
import { style } from '@vanilla-extract/css';
import { responsiveStyle } from 'braid-design-system/css';
-import { monospaceFontFamily } from '.';
+// SEEK's former font + GitHub defaults
+export const monospaceFontFamily =
+ "'Roboto Mono',SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace";
// Roboto Mono metrics from seek-oss.github.io/capsize
const monospaceFontMetrics = {
diff --git a/styles/img.css.ts b/styles/img.css.ts
deleted file mode 100644
index 11cc3550..00000000
--- a/styles/img.css.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { composeStyles, style } from '@vanilla-extract/css';
-import { atoms, vars } from 'braid-design-system/css';
-
-const atomStyle = atoms({
- borderRadius: 'large',
- display: 'block',
-});
-
-const rawStyle = style({
- borderColor: vars.borderColor.neutralLight,
- borderWidth: vars.borderWidth.standard,
- borderStyle: 'solid',
-});
-
-export const img = composeStyles(atomStyle, rawStyle);
diff --git a/styles/index.ts b/styles/index.ts
deleted file mode 100644
index 6707a15c..00000000
--- a/styles/index.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-// https://github.com/seek-oss/braid-design-system/blob/braid-design-system%4033.5.0/packages/braid-design-system/src/lib/color/palette.ts#L2-L14
-export const codeBackgroundColor = {
- // Braid grey.50
- lightMode: '#F7F8FB',
-
- // Braid grey.900
- darkMode: '#0E131B',
-};
-
-// SEEK's former font + GitHub defaults
-export const monospaceFontFamily =
- "'Roboto Mono',SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace";