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";