scoobie 18.2.0 → 19.0.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/README.md CHANGED
@@ -78,16 +78,33 @@ export const MyFirstBlockquote = () => (
78
78
 
79
79
  ### CodeBlock
80
80
 
81
- Render lines of code with [Prism] syntax highlighting.
82
-
83
- [prism]: https://github.com/PrismJS/prism
81
+ Render a rich [`CodeContainer`](#codecontainer) with interactive copy & GraphQL playground link buttons.
84
82
 
85
83
  ```tsx
86
84
  import React from 'react';
87
85
  import { CodeBlock } from 'scoobie';
88
86
 
89
87
  export const MyFirstCodeBlock = () => (
90
- <CodeBlock language="javascript">console.log('hello, world');</CodeBlock>
88
+ <CodeBlock language="javascript" label="Here is the code">
89
+ console.log('hello, world');
90
+ </CodeBlock>
91
+ );
92
+ ```
93
+
94
+ ### CodeContainer
95
+
96
+ Render code with [Prism] syntax highlighting, with optional `lineNumbers`.
97
+
98
+ [prism]: https://github.com/PrismJS/prism
99
+
100
+ ```tsx
101
+ import React from 'react';
102
+ import { CodeContainer } from 'scoobie';
103
+
104
+ export const MyFirstCodeContainer = () => (
105
+ <CodeContainer language="javascript">
106
+ console.log('hello, world');
107
+ </CodeContainer>
91
108
  );
92
109
  ```
93
110
 
@@ -217,33 +234,6 @@ export const SomeLinks = () => (
217
234
  );
218
235
  ```
219
236
 
220
- ### Table
221
-
222
- ```tsx
223
- import React, { Fragment } from 'react';
224
- import { Table, TableRow } from 'scoobie';
225
-
226
- export const MyFirstTable = () => (
227
- <Table header={['Column A', 'Column B']}>
228
- <TableRow>
229
- <Fragment>This is body cell A1.</Fragment>
230
- <Fragment>B1</Fragment>
231
- </TableRow>
232
-
233
- <TableRow>
234
- <Fragment>A2</Fragment>
235
- <Fragment>This is body cell B2.</Fragment>
236
- </TableRow>
237
- </Table>
238
- );
239
- ```
240
-
241
- ### TableRow
242
-
243
- `<tr>` component for use with [Table](#table).
244
-
245
- Row children are flattened then wrapped with `<td>`s.
246
-
247
237
  ## Styling reference
248
238
 
249
239
  Scoobie distributes some vanilla-extract styles via `scoobie/styles` submodules.
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "license": "MIT",
5
5
  "main": "src/index.ts",
6
6
  "sideEffects": false,
7
- "version": "18.2.0",
7
+ "version": "19.0.0",
8
8
  "dependencies": {
9
9
  "@capsizecss/core": "^4.0.0",
10
10
  "@vanilla-extract/css": "^1.2.3",
@@ -55,13 +55,13 @@
55
55
  "scripts": {
56
56
  "format": "sku format",
57
57
  "lint": "sku lint",
58
- "loki:test": "loki test --host host.docker.internal --port 8081",
58
+ "loki:test": "loki test --port 12228",
59
59
  "loki:test:ci": "cp -R dist-storybook/. dist-storybook-tmp/ && loki --requireReference --reactUri file:./dist-storybook-tmp --chromeFlags='--headless --hide-scrollbars --no-sandbox'",
60
- "loki:update": "loki update --host host.docker.internal --port 8081",
60
+ "loki:update": "loki update --port 12228",
61
61
  "release": "changeset publish",
62
62
  "stage": "changeset version && yarn format",
63
63
  "storybook:build": "storybook build --output-dir dist-storybook",
64
- "storybook:start": "storybook dev",
64
+ "storybook:start": "storybook dev --port 12228",
65
65
  "test": "sku test",
66
66
  "test:ci": "sku test --coverage"
67
67
  },
@@ -1,27 +1,19 @@
1
1
  import { Box, Heading, Secondary, Stack } from 'braid-design-system';
2
- import React from 'react';
3
2
 
4
- import { DEFAULT_SIZE, SIZE_TO_SPACE, type Size } from '../private/size';
5
3
  import type { StackChildrenProps } from '../private/types';
6
4
 
7
5
  import * as styles from './Blockquote.css';
8
6
 
9
- interface Props extends StackChildrenProps {
10
- size: Size;
11
- }
7
+ interface Props extends StackChildrenProps {}
12
8
 
13
- export const Blockquote = ({ children, size = DEFAULT_SIZE }: Props) => {
14
- const space = SIZE_TO_SPACE[size];
9
+ export const Blockquote = ({ children }: Props) => (
10
+ <Box className={styles.quoteBlock} padding="medium">
11
+ <Stack space="medium">{children}</Stack>
15
12
 
16
- return (
17
- <Box className={styles.quoteBlock} padding={space}>
18
- <Stack space={space}>{children}</Stack>
19
-
20
- <Box position="absolute" right={0} top={0} userSelect="none" zIndex={0}>
21
- <Heading component="div" level="2">
22
- <Secondary>”</Secondary>
23
- </Heading>
24
- </Box>
13
+ <Box position="absolute" right={0} top={0} userSelect="none" zIndex={0}>
14
+ <Heading component="div" level="2">
15
+ <Secondary>”</Secondary>
16
+ </Heading>
25
17
  </Box>
26
- );
27
- };
18
+ </Box>
19
+ );
@@ -1,30 +1,23 @@
1
1
  import { IconVideo, Text, TextLink } from 'braid-design-system';
2
- import React from 'react';
3
-
4
- import { SIZE_TO_SMALLER, type Size } from '../../private/size';
5
2
 
6
3
  interface Props {
7
4
  query: string;
8
5
  variables: string | undefined;
9
6
  graphqlPlayground: string;
10
- size: Size;
11
7
  }
12
8
 
13
9
  export const GraphQLPlaygroundAction = ({
14
10
  query,
15
11
  variables,
16
12
  graphqlPlayground,
17
- size,
18
13
  }: Props) => {
19
14
  const playgroundUrl = new URL(graphqlPlayground);
20
15
  playgroundUrl.searchParams.set('query', query);
21
16
  playgroundUrl.searchParams.set('variables', variables ?? '{}');
22
17
  const href = playgroundUrl.toString();
23
18
 
24
- const smallerSize = SIZE_TO_SMALLER[size];
25
-
26
19
  return (
27
- <Text size={smallerSize} weight="medium">
20
+ <Text size="small" weight="medium">
28
21
  <TextLink
29
22
  href={href}
30
23
  icon={<IconVideo alignY="lowercase" />}
@@ -1,35 +1,22 @@
1
1
  import { Box, Stack, Text, TextLinkButton } from 'braid-design-system';
2
2
  import { parse } from 'jsonc-parser';
3
- import { Highlight } from 'prism-react-renderer';
4
- import React, { useEffect, useState } from 'react';
3
+ import { useEffect, useState } from 'react';
5
4
 
6
- import { Prism, themes } from '../private/Prism';
7
5
  import { ScrollableInline } from '../private/ScrollableInline';
8
- import {
9
- DEFAULT_SIZE,
10
- SIZE_TO_SMALLER,
11
- SIZE_TO_TABLE_PADDING,
12
- type Size,
13
- } from '../private/size';
14
6
 
15
7
  import { type CodeChildProps, normaliseChildren } from './CodeBlock/CodeChild';
16
8
  import { GraphQLPlaygroundAction } from './CodeBlock/GraphQLPlaygroundAction';
17
- import { LineNumbers } from './CodeBlock/LineNumbers';
18
- import { Lines } from './CodeBlock/Lines';
9
+ import { CodeContainer } from './CodeContainer';
19
10
  import { CopyableText } from './CopyableText';
20
11
 
21
- import * as styles from './CodeBlock.css';
22
-
23
12
  interface Props {
24
13
  children: readonly CodeChildProps[] | string;
25
14
  graphqlPlayground?: string;
26
15
  initialIndex?: number;
27
- label?: string;
28
- language?: string;
29
- size?: Size;
16
+ label: string;
17
+ language: string;
30
18
  trim?: boolean;
31
19
  lineNumbers?: boolean;
32
- copy?: boolean;
33
20
  }
34
21
 
35
22
  export const CodeBlock = ({
@@ -38,10 +25,8 @@ export const CodeBlock = ({
38
25
  initialIndex = 0,
39
26
  label: rawLabel,
40
27
  language: rawLanguage,
41
- size = DEFAULT_SIZE,
42
28
  trim = true,
43
29
  lineNumbers = true,
44
- copy = true,
45
30
  }: Props) => {
46
31
  const children = normaliseChildren(
47
32
  typeof rawChildren === 'string'
@@ -56,9 +41,6 @@ export const CodeBlock = ({
56
41
  trim,
57
42
  );
58
43
 
59
- const smallerSize = SIZE_TO_SMALLER[size];
60
- const tablePadding = SIZE_TO_TABLE_PADDING[size];
61
-
62
44
  const [index, setIndex] = useState({ dirty: false, value: initialIndex });
63
45
 
64
46
  useEffect(
@@ -84,87 +66,64 @@ export const CodeBlock = ({
84
66
 
85
67
  const graphqlPlaygroundButton =
86
68
  children[0].language === 'graphql' && graphqlPlayground ? (
87
- <Box component="span" paddingLeft={tablePadding}>
69
+ <Box component="span" paddingLeft="small">
88
70
  <GraphQLPlaygroundAction
89
71
  graphqlPlayground={graphqlPlayground}
90
- size={size}
91
72
  query={children[0].code}
92
73
  variables={variables}
93
74
  />
94
75
  </Box>
95
76
  ) : undefined;
96
77
 
97
- const topRow =
98
- children.some(({ label }) => label) || copy || graphqlPlaygroundButton;
99
-
100
78
  return (
101
- <Stack space={tablePadding}>
102
- {topRow ? (
103
- <ScrollableInline whiteSpace="nowrap">
104
- <Box display="flex" justifyContent="spaceBetween">
105
- <Box display="flex">
106
- {children.map(({ label }, labelIndex) =>
107
- label ? (
108
- <Box
109
- component="span"
110
- key={label}
111
- paddingLeft={labelIndex === 0 ? undefined : tablePadding}
79
+ <Stack space="small">
80
+ <ScrollableInline whiteSpace="nowrap">
81
+ <Box display="flex" justifyContent="spaceBetween">
82
+ <Box display="flex">
83
+ {children.map(({ label }, labelIndex) =>
84
+ label ? (
85
+ <Box
86
+ component="span"
87
+ key={label}
88
+ paddingLeft={labelIndex === 0 ? undefined : 'small'}
89
+ >
90
+ <Text
91
+ size="small"
92
+ tone={index.value === labelIndex ? 'secondary' : undefined}
93
+ weight="medium"
112
94
  >
113
- <Text
114
- size={smallerSize}
115
- tone={
116
- index.value === labelIndex ? 'secondary' : undefined
117
- }
118
- weight="medium"
119
- >
120
- {children.length === 1 || index.value === labelIndex ? (
121
- label
122
- ) : (
123
- <TextLinkButton
124
- onClick={() =>
125
- setIndex({ dirty: true, value: labelIndex })
126
- }
127
- >
128
- {label}
129
- </TextLinkButton>
130
- )}
131
- </Text>
132
- </Box>
133
- ) : null,
134
- )}
135
- </Box>
136
-
137
- <Box display="flex">
138
- {copy ? (
139
- <Box component="span" paddingLeft={tablePadding}>
140
- <CopyableText size={smallerSize}>{child.code}</CopyableText>
95
+ {children.length === 1 || index.value === labelIndex ? (
96
+ label
97
+ ) : (
98
+ <TextLinkButton
99
+ onClick={() =>
100
+ setIndex({ dirty: true, value: labelIndex })
101
+ }
102
+ >
103
+ {label}
104
+ </TextLinkButton>
105
+ )}
106
+ </Text>
141
107
  </Box>
142
- ) : null}
143
-
144
- {graphqlPlaygroundButton}
145
- </Box>
108
+ ) : null,
109
+ )}
146
110
  </Box>
147
- </ScrollableInline>
148
- ) : null}
149
-
150
- <Box borderRadius="large" className={styles.codeContainer}>
151
- <Highlight
152
- prism={Prism}
153
- code={child.code}
154
- language={child.language}
155
- theme={themes.github}
156
- >
157
- {({ getTokenProps, tokens }) => (
158
- <Box display="flex">
159
- {lineNumbers ? (
160
- <LineNumbers count={tokens.length} size={size} />
161
- ) : null}
162
111
 
163
- <Lines getTokenProps={getTokenProps} lines={tokens} size={size} />
112
+ <Box display="flex">
113
+ <Box component="span" paddingLeft="small">
114
+ <CopyableText size="small">{child.code}</CopyableText>
164
115
  </Box>
165
- )}
166
- </Highlight>
167
- </Box>
116
+
117
+ {graphqlPlaygroundButton}
118
+ </Box>
119
+ </Box>
120
+ </ScrollableInline>
121
+
122
+ <CodeContainer
123
+ code={child.code}
124
+ language={child.language}
125
+ lineNumbers={lineNumbers}
126
+ />
168
127
  </Stack>
169
128
  );
170
129
  };
@@ -1,4 +1,4 @@
1
- import { composeStyles, style } from '@vanilla-extract/css';
1
+ import { style } from '@vanilla-extract/css';
2
2
  import { calc } from '@vanilla-extract/css-utils';
3
3
  import { responsiveStyle, vars } from 'braid-design-system/css';
4
4
  import { darken } from 'polished';
@@ -13,26 +13,24 @@ export const lineNumberContainer = style({
13
13
  userSelect: 'none',
14
14
  });
15
15
 
16
- export const codeContainer = composeStyles(
17
- style({
16
+ export const codeContainer = style([
17
+ {
18
18
  backgroundColor: codeBackgroundColor,
19
19
  borderColor: darken(0.05, codeBackgroundColor),
20
20
  borderStyle: 'solid',
21
21
  borderWidth: vars.borderWidth.standard,
22
22
 
23
23
  overflow: 'auto',
24
- }),
24
+ },
25
25
 
26
- style(
27
- responsiveStyle({
28
- mobile: {
29
- // Roughly 15 lines of code at standard size.
30
- maxHeight: calc.multiply(vars.grid, 90),
31
- },
32
- tablet: {
33
- // Roughly 30 lines of code at standard size.
34
- maxHeight: calc.multiply(vars.grid, 172),
35
- },
36
- }),
37
- ),
38
- );
26
+ responsiveStyle({
27
+ mobile: {
28
+ // Roughly 15 lines of code at standard size.
29
+ maxHeight: calc.multiply(vars.grid, 90),
30
+ },
31
+ tablet: {
32
+ // Roughly 30 lines of code at standard size.
33
+ maxHeight: calc.multiply(vars.grid, 172),
34
+ },
35
+ }),
36
+ ]);
@@ -0,0 +1,78 @@
1
+ import { Box, Stack } from 'braid-design-system';
2
+ import { Highlight, type Token } from 'prism-react-renderer';
3
+
4
+ import { Prism, themes } from '../private/Prism';
5
+
6
+ import * as styles from './CodeContainer.css';
7
+ import * as codeStyles from '../../styles/code.css';
8
+
9
+ export const CodeContainer = ({
10
+ code,
11
+ language,
12
+ lineNumbers,
13
+ }: {
14
+ code: string;
15
+ language: string;
16
+ lineNumbers?: boolean;
17
+ }) => (
18
+ <Box borderRadius="large" className={styles.codeContainer}>
19
+ <Highlight
20
+ prism={Prism}
21
+ code={code}
22
+ language={language}
23
+ theme={themes.github}
24
+ >
25
+ {({ getTokenProps, tokens }) => (
26
+ <Box display="flex">
27
+ {lineNumbers ? <LineNumbers count={tokens.length} /> : null}
28
+
29
+ <Lines getTokenProps={getTokenProps} lines={tokens} />
30
+ </Box>
31
+ )}
32
+ </Highlight>
33
+ </Box>
34
+ );
35
+
36
+ const LineNumbers = ({ count }: { count: number }) => {
37
+ const numbers = [...new Array(count)].map((_, index) => index + 1);
38
+
39
+ return (
40
+ <Box aria-hidden className={styles.lineNumberContainer} padding="medium">
41
+ <Stack align="right" space="small">
42
+ {numbers.map((number) => (
43
+ <Box className={codeStyles.code} key={number}>
44
+ <Box component="pre">{number}</Box>
45
+ </Box>
46
+ ))}
47
+ </Stack>
48
+ </Box>
49
+ );
50
+ };
51
+
52
+ type HighlightProps = Parameters<
53
+ Parameters<typeof Highlight>[0]['children']
54
+ >[0];
55
+
56
+ const Lines = ({
57
+ getTokenProps,
58
+ lines,
59
+ }: {
60
+ getTokenProps: HighlightProps['getTokenProps'];
61
+ lines: Token[][];
62
+ }) => (
63
+ <Box padding="medium">
64
+ <Stack space="small">
65
+ {lines.map((line, lineIndex) => (
66
+ <Box className={codeStyles.code} key={lineIndex}>
67
+ <Box component="pre">
68
+ {line.map((token, tokenIndex) => {
69
+ const props = getTokenProps({ token });
70
+
71
+ return <Box component="span" {...props} key={tokenIndex} />;
72
+ })}
73
+ </Box>
74
+ </Box>
75
+ ))}
76
+ </Stack>
77
+ </Box>
78
+ );
package/src/index.ts CHANGED
@@ -1,10 +1,9 @@
1
1
  export { Blockquote } from './components/Blockquote';
2
2
  export { CodeBlock } from './components/CodeBlock';
3
+ export { CodeContainer } from './components/CodeContainer';
3
4
  export { CopyableText } from './components/CopyableText';
4
5
  export { InlineCode } from './components/InlineCode';
5
6
  export { InternalLink } from './components/InternalLink';
6
7
  export { ScoobieLink } from './components/ScoobieLink';
7
8
  export { ScoobieLinkProvider } from './components/ScoobieLinkProvider';
8
9
  export { SmartTextLink } from './components/SmartTextLink';
9
- export { Table } from './components/Table';
10
- export { TableRow } from './components/TableRow';
@@ -1,9 +1,7 @@
1
1
  import { createStyleObject, getCapHeight } from '@capsizecss/core';
2
- import { styleVariants } from '@vanilla-extract/css';
2
+ import { style } from '@vanilla-extract/css';
3
3
  import { responsiveStyle } from 'braid-design-system/css';
4
4
 
5
- import type { Size } from '../src/private/size';
6
-
7
5
  import { monospaceFontFamily } from '.';
8
6
 
9
7
  // Roboto Mono metrics from seek-oss.github.io/capsize
@@ -26,53 +24,33 @@ const tokens = {
26
24
  grid: 4,
27
25
  typography: {
28
26
  code: {
29
- // Matches `small` text
30
- standard: {
31
- mobile: {
32
- fontSize: 14,
33
- rows: 5,
34
- },
35
- tablet: {
36
- fontSize: 14,
37
- rows: 5,
38
- },
27
+ mobile: {
28
+ fontSize: 14,
29
+ rows: 5,
39
30
  },
40
- // Matches `standard` text
41
- large: {
42
- mobile: {
43
- fontSize: 16,
44
- rows: 6,
45
- },
46
- tablet: {
47
- fontSize: 16,
48
- rows: 6,
49
- },
31
+ tablet: {
32
+ fontSize: 14,
33
+ rows: 5,
50
34
  },
51
35
  },
52
36
  },
53
37
  };
54
38
 
55
- const monospaceFontStylesForTarget = (
56
- size: Size,
57
- target: 'mobile' | 'tablet',
58
- ) =>
39
+ const monospaceFontStylesForTarget = (target: 'mobile' | 'tablet') =>
59
40
  createStyleObject({
60
41
  capHeight: getCapHeight({
61
- fontSize: tokens.typography.code[size][target].fontSize,
42
+ fontSize: tokens.typography.code[target].fontSize,
62
43
  fontMetrics: monospaceFontMetrics,
63
44
  }),
64
45
  fontMetrics: monospaceFontMetrics,
65
- leading: tokens.typography.code[size][target].rows * tokens.grid,
46
+ leading: tokens.typography.code[target].rows * tokens.grid,
66
47
  });
67
48
 
68
- export const code = styleVariants(
69
- { standard: null, large: null },
70
- (_, size) => ({
71
- fontFamily: monospaceFontFamily,
49
+ export const code = style({
50
+ fontFamily: monospaceFontFamily,
72
51
 
73
- ...responsiveStyle({
74
- mobile: monospaceFontStylesForTarget(size, 'mobile'),
75
- tablet: monospaceFontStylesForTarget(size, 'tablet'),
76
- }),
52
+ ...responsiveStyle({
53
+ mobile: monospaceFontStylesForTarget('mobile'),
54
+ tablet: monospaceFontStylesForTarget('tablet'),
77
55
  }),
78
- );
56
+ });
@@ -1,28 +0,0 @@
1
- import { Box, Stack } from 'braid-design-system';
2
- import React from 'react';
3
-
4
- import type { Size } from '../../private/size';
5
-
6
- import { code } from '../../../styles/code.css';
7
- import * as styles from '../CodeBlock.css';
8
-
9
- interface Props {
10
- count: number;
11
- size: Size;
12
- }
13
-
14
- export const LineNumbers = ({ count, size }: Props) => {
15
- const numbers = [...new Array(count)].map((_, index) => index + 1);
16
-
17
- return (
18
- <Box aria-hidden className={styles.lineNumberContainer} padding="medium">
19
- <Stack align="right" space="small">
20
- {numbers.map((number) => (
21
- <Box className={code[size]} key={number}>
22
- <Box component="pre">{number}</Box>
23
- </Box>
24
- ))}
25
- </Stack>
26
- </Box>
27
- );
28
- };
@@ -1,35 +0,0 @@
1
- import { Box, Stack } from 'braid-design-system';
2
- import type { Highlight } from 'prism-react-renderer';
3
- import React from 'react';
4
-
5
- import type { Size } from '../../private/size';
6
-
7
- import { code } from '../../../styles/code.css';
8
-
9
- type Highlight = Parameters<Parameters<typeof Highlight>[0]['children']>[0];
10
-
11
- type Token = Parameters<Highlight['getTokenProps']>[0]['token'];
12
-
13
- interface Props {
14
- getTokenProps: Highlight['getTokenProps'];
15
- lines: Token[][];
16
- size: Size;
17
- }
18
-
19
- export const Lines = ({ getTokenProps, lines, size }: Props) => (
20
- <Box padding="medium">
21
- <Stack space="small">
22
- {lines.map((line, lineIndex) => (
23
- <Box className={code[size]} key={lineIndex}>
24
- <Box component="pre">
25
- {line.map((token, tokenIndex) => {
26
- const props = getTokenProps({ token });
27
-
28
- return <Box component="span" {...props} key={tokenIndex} />;
29
- })}
30
- </Box>
31
- </Box>
32
- ))}
33
- </Stack>
34
- </Box>
35
- );
@@ -1,71 +0,0 @@
1
- import { Box, type Stack } from 'braid-design-system';
2
- import React, { type ComponentProps, type ReactNode } from 'react';
3
-
4
- import { BaseTable } from '../private/Table';
5
- import {
6
- DEFAULT_TABLE_TYPE,
7
- type TableAlign,
8
- TableContext,
9
- type TableType,
10
- } from '../private/TableContext';
11
- import { DEFAULT_SIZE, type Size } from '../private/size';
12
-
13
- import { TableRow } from './TableRow';
14
-
15
- interface BaseProps {
16
- align?: readonly TableAlign[];
17
- children: ReactNode;
18
- header: ComponentProps<typeof Stack>['children'] | readonly string[];
19
- size?: Size;
20
- type?: TableType;
21
- width?: 'full';
22
- }
23
-
24
- type Props = BaseProps &
25
- (
26
- | {
27
- overflowX: 'scroll';
28
- whiteSpace?: 'nowrap';
29
- }
30
- | {
31
- overflowX?: never;
32
- whiteSpace?: never;
33
- }
34
- );
35
-
36
- export const Table = ({
37
- align,
38
- children,
39
- header,
40
- overflowX,
41
- size = DEFAULT_SIZE,
42
- type = DEFAULT_TABLE_TYPE,
43
- whiteSpace,
44
- width,
45
- }: Props) => (
46
- <BaseTable overflowX={overflowX} whiteSpace={whiteSpace} width={width}>
47
- <TableContext.Provider
48
- value={{
49
- align,
50
- component: 'th',
51
- size,
52
- type,
53
- }}
54
- >
55
- <Box component="thead">
56
- <TableRow>{header}</TableRow>
57
- </Box>
58
- </TableContext.Provider>
59
-
60
- <TableContext.Provider
61
- value={{
62
- align,
63
- component: 'td',
64
- size,
65
- type,
66
- }}
67
- >
68
- <Box component="tbody">{children}</Box>
69
- </TableContext.Provider>
70
- </BaseTable>
71
- );
@@ -1,32 +0,0 @@
1
- import { type Stack, Text } from 'braid-design-system';
2
- import React, { Children, type ComponentProps, useContext } from 'react';
3
- import flattenChildren from 'react-keyed-flatten-children';
4
-
5
- import { TableCell } from '../private/TableCell';
6
- import { TableContext } from '../private/TableContext';
7
- import { BaseTableRow } from '../private/TableRow';
8
-
9
- interface Props {
10
- children: ComponentProps<typeof Stack>['children'] | readonly string[];
11
- selected?: boolean;
12
- }
13
-
14
- export const TableRow = ({ children, selected }: Props) => {
15
- const { align, component } = useContext(TableContext);
16
-
17
- return (
18
- <BaseTableRow selected={selected}>
19
- {Children.map(flattenChildren(children), (child, index) => (
20
- <TableCell align={align?.[index]} component={component}>
21
- {typeof child === 'number' || typeof child === 'string' ? (
22
- <Text weight={component === 'td' ? undefined : 'strong'}>
23
- {child}
24
- </Text>
25
- ) : (
26
- child
27
- )}
28
- </TableCell>
29
- ))}
30
- </BaseTableRow>
31
- );
32
- };
@@ -1,10 +0,0 @@
1
- import { style } from '@vanilla-extract/css';
2
-
3
- export const fullWidth = style({
4
- width: '100%',
5
- });
6
-
7
- export const table = style({
8
- borderCollapse: 'separate',
9
- borderSpacing: 0,
10
- });
@@ -1,36 +0,0 @@
1
- import { Box } from 'braid-design-system';
2
- import React, { Fragment, type ReactNode } from 'react';
3
-
4
- import { ScrollableInline } from './ScrollableInline';
5
-
6
- import * as styles from './Table.css';
7
-
8
- interface BaseTableProps {
9
- children: ReactNode;
10
- overflowX?: 'scroll';
11
- whiteSpace?: 'nowrap';
12
- width?: 'full';
13
- }
14
-
15
- export const BaseTable = ({
16
- children,
17
- overflowX,
18
- whiteSpace,
19
- width,
20
- }: BaseTableProps) => {
21
- const Wrapper = overflowX === 'scroll' ? ScrollableInline : Fragment;
22
-
23
- return (
24
- <Wrapper {...(overflowX === 'scroll' ? { whiteSpace } : {})}>
25
- <Box
26
- component="table"
27
- className={{
28
- [styles.table]: true,
29
- [styles.fullWidth]: width === 'full',
30
- }}
31
- >
32
- {children}
33
- </Box>
34
- </Wrapper>
35
- );
36
- };
@@ -1,108 +0,0 @@
1
- import { styleVariants } from '@vanilla-extract/css';
2
- import { vars } from 'braid-design-system/css';
3
-
4
- import { SIZE_TO_TABLE_PADDING, type Size } from './size';
5
-
6
- import { tableRowSelection } from './TableRow.css';
7
-
8
- export const tableCell = styleVariants({
9
- stripe: {
10
- borderBottomWidth: vars.borderWidth.standard,
11
- borderColor: vars.borderColor.neutralLight,
12
- borderRightWidth: vars.borderWidth.standard,
13
- borderStyle: 'solid',
14
- verticalAlign: 'top',
15
-
16
- ':first-child': {
17
- borderLeftWidth: vars.borderWidth.standard,
18
- },
19
- },
20
- subtle: {
21
- borderBottomWidth: vars.borderWidth.standard,
22
- borderColor: vars.borderColor.neutralLight,
23
- borderStyle: 'solid',
24
- verticalAlign: 'top',
25
-
26
- ':first-child': {
27
- paddingLeft: 0,
28
- },
29
-
30
- ':last-child': {
31
- paddingRight: 0,
32
- },
33
- },
34
- });
35
-
36
- const tdForSize = (size: Size) =>
37
- styleVariants({
38
- stripe: {
39
- selectors: {
40
- [`${tableRowSelection} &:first-child`]: {
41
- borderLeftColor: vars.borderColor.focus,
42
- borderLeftWidth: vars.borderWidth.large,
43
- },
44
- [`${tableRowSelection} &:last-child`]: {
45
- borderRightColor: vars.borderColor.focus,
46
- borderRightWidth: vars.borderWidth.large,
47
- },
48
- 'tr:last-child &:first-child': {
49
- borderBottomLeftRadius: vars.borderRadius.large,
50
- },
51
- 'tr:last-child &:last-child': {
52
- borderBottomRightRadius: vars.borderRadius.large,
53
- },
54
- },
55
- },
56
- subtle: {
57
- selectors: {
58
- [`${tableRowSelection} &:first-child`]: {
59
- borderLeftColor: vars.borderColor.focus,
60
- borderLeftWidth: vars.borderWidth.large,
61
- borderLeftStyle: 'solid',
62
- paddingLeft: vars.space[SIZE_TO_TABLE_PADDING[size]],
63
- },
64
- [`${tableRowSelection} &:last-child`]: {
65
- borderRightColor: vars.borderColor.focus,
66
- borderRightWidth: vars.borderWidth.large,
67
- borderRightStyle: 'solid',
68
- paddingRight: vars.space[SIZE_TO_TABLE_PADDING[size]],
69
- },
70
- 'tr:last-child &': {
71
- borderBottomWidth: 0,
72
- paddingBottom: 0,
73
- },
74
- },
75
- },
76
- });
77
-
78
- export const td = {
79
- large: tdForSize('large'),
80
- standard: tdForSize('standard'),
81
- };
82
-
83
- export const th = styleVariants({
84
- stripe: {
85
- selectors: {
86
- 'tr:first-child &': {
87
- borderTopWidth: 1,
88
- },
89
- 'tr:first-child &:first-child': {
90
- borderTopLeftRadius: vars.borderRadius.large,
91
- },
92
- 'tr:first-child &:last-child': {
93
- borderTopRightRadius: vars.borderRadius.large,
94
- },
95
- },
96
- },
97
- subtle: {
98
- selectors: {
99
- 'tr:first-child &': {
100
- paddingTop: 0,
101
- },
102
- 'tr:last-child &': {
103
- borderBottomColor: vars.borderColor.field,
104
- borderBottomWidth: vars.borderWidth.large,
105
- },
106
- },
107
- },
108
- });
@@ -1,34 +0,0 @@
1
- import { Box, Stack } from 'braid-design-system';
2
- import React, { useContext } from 'react';
3
-
4
- import { type TableAlign, TableContext } from './TableContext';
5
- import { SIZE_TO_SPACE, SIZE_TO_TABLE_PADDING } from './size';
6
- import type { StackChildrenProps } from './types';
7
-
8
- import * as styles from './TableCell.css';
9
-
10
- interface Props extends StackChildrenProps {
11
- align?: TableAlign | null;
12
- component: 'td' | 'th';
13
- }
14
-
15
- export const TableCell = ({ align, children, component }: Props) => {
16
- const { size, type } = useContext(TableContext);
17
-
18
- const padding = SIZE_TO_TABLE_PADDING[size];
19
- const space = SIZE_TO_SPACE[size];
20
-
21
- return (
22
- <Box
23
- className={[
24
- styles.tableCell[type],
25
- component === 'td' ? styles.td[size][type] : styles.th[type],
26
- ]}
27
- component={component}
28
- padding={padding}
29
- textAlign={align ?? (component === 'td' ? 'left' : 'center')}
30
- >
31
- <Stack space={space}>{children}</Stack>
32
- </Box>
33
- );
34
- };
@@ -1,26 +0,0 @@
1
- import { createContext } from 'react';
2
-
3
- import { DEFAULT_SIZE, type Size } from './size';
4
-
5
- interface TableContextValue {
6
- align?: readonly TableAlign[];
7
- component: TableCellComponent;
8
- size: Size;
9
- type: TableType;
10
- }
11
-
12
- export type TableAlign = 'left' | 'center' | 'right';
13
-
14
- type TableCellComponent = 'td' | 'th';
15
-
16
- export type TableType = 'stripe' | 'subtle';
17
-
18
- export const DEFAULT_TABLE_CELL_COMPONENT: TableCellComponent = 'td';
19
-
20
- export const DEFAULT_TABLE_TYPE: TableType = 'stripe';
21
-
22
- export const TableContext = createContext<TableContextValue>({
23
- component: DEFAULT_TABLE_CELL_COMPONENT,
24
- size: DEFAULT_SIZE,
25
- type: DEFAULT_TABLE_TYPE,
26
- });
@@ -1,16 +0,0 @@
1
- import { style, styleVariants } from '@vanilla-extract/css';
2
-
3
- import { codeBackgroundColor } from '../../styles';
4
-
5
- export const tableRow = styleVariants({
6
- stripe: {
7
- selectors: {
8
- 'tbody &:nth-child(odd)': {
9
- backgroundColor: codeBackgroundColor,
10
- },
11
- },
12
- },
13
- subtle: {},
14
- });
15
-
16
- export const tableRowSelection = style({});
@@ -1,28 +0,0 @@
1
- import { Box } from 'braid-design-system';
2
- import React, { useContext } from 'react';
3
-
4
- import { TableContext } from '../private/TableContext';
5
-
6
- import type { StackChildrenProps } from './types';
7
-
8
- import * as styles from './TableRow.css';
9
-
10
- interface Props extends StackChildrenProps {
11
- selected?: boolean;
12
- }
13
-
14
- export const BaseTableRow = ({ children, selected }: Props) => {
15
- const { type } = useContext(TableContext);
16
-
17
- return (
18
- <Box
19
- className={{
20
- [styles.tableRow[type]]: true,
21
- [styles.tableRowSelection]: selected,
22
- }}
23
- component="tr"
24
- >
25
- {children}
26
- </Box>
27
- );
28
- };
@@ -1,34 +0,0 @@
1
- import { Box, Stack } from 'braid-design-system';
2
- import React, { type FunctionComponent } from 'react';
3
-
4
- import { SIZE_TO_SPACE, type Size } from './size';
5
- import type { StackChildrenProps } from './types';
6
-
7
- import * as styles from './Wrapper.css';
8
-
9
- export type WrapperComponent = FunctionComponent<StackChildrenProps>;
10
-
11
- type WrapperProps = StackChildrenProps & {
12
- component?: WrapperComponent;
13
- size: Size;
14
- };
15
-
16
- export const Wrapper = ({
17
- children,
18
- component: Component,
19
- size,
20
- }: WrapperProps) => {
21
- const space = SIZE_TO_SPACE[size];
22
-
23
- return (
24
- <Box className={styles.wrapper}>
25
- <Stack space={space}>
26
- {typeof Component === 'undefined' ? (
27
- children
28
- ) : (
29
- <Component>{children}</Component>
30
- )}
31
- </Stack>
32
- </Box>
33
- );
34
- };
@@ -1,28 +0,0 @@
1
- type TablePadding = 'small' | 'medium';
2
-
3
- type Space = 'medium' | 'large';
4
-
5
- export const DEFAULT_SIZE: Size = 'standard';
6
-
7
- export const SIZES = ['standard', 'large'] as const;
8
-
9
- export const SMALLER_SIZES = ['small', 'standard'] as const;
10
-
11
- export type SmallerSize = (typeof SMALLER_SIZES)[number];
12
-
13
- export type Size = (typeof SIZES)[number];
14
-
15
- export const SIZE_TO_SMALLER: Record<Size, SmallerSize> = {
16
- standard: 'small',
17
- large: 'standard',
18
- };
19
-
20
- export const SIZE_TO_TABLE_PADDING: Record<Size, TablePadding> = {
21
- standard: 'small',
22
- large: 'medium',
23
- };
24
-
25
- export const SIZE_TO_SPACE: Record<Size, Space> = {
26
- standard: 'medium',
27
- large: 'large',
28
- };