diff --git a/packages/dev/s2-docs/pages/s2/style-macro.mdx b/packages/dev/s2-docs/pages/s2/style-macro.mdx
index 4d312d9a2ca..8592c288d17 100644
--- a/packages/dev/s2-docs/pages/s2/style-macro.mdx
+++ b/packages/dev/s2-docs/pages/s2/style-macro.mdx
@@ -1,7 +1,5 @@
import {Layout} from '../../src/Layout';
import {InlineAlert, Heading, Content, Link} from '@react-spectrum/s2';
-import {S2Colors} from '../../src/S2Colors';
-import {S2Typography} from '../../src/S2Typography';
import {StyleMacroProperties} from '../../src/types';
import {getPropertyDefinitions, getShorthandDefinitions} from '../../src/styleProperties';
export default Layout;
@@ -17,23 +15,11 @@ The `style` macro supports a constrained set of values per property that conform
## Colors
All Spectrum 2 color tokens are available across color properties (e.g., `backgroundColor`, `color`, `borderColor`).
-`baseColors` consists of the semantic and global colors listed below.
-
-
## Dimensions
-Spacing props like `margin` and `padding` accept values on a **4px grid**. These are specified in `px` and get converted to `rem`. In addition to numbers, these named options are available:
-
-- `edge-to-text` – default spacing between the edge of a control and its text. Relative to control height.
-- `pill` – default spacing between the edge of a pill-shaped control and its text. Relative to control height.
-- `text-to-control` – default spacing between text and a control (e.g., label and input). Scales with font size.
-- `text-to-visual` – default spacing between text and a visual element (e.g., icon). Scales with font size.
-
-Size props like `width` and `height` accept arbitrary pixel values. Values are converted to `rem` and multiplied by 1.25x on touch devices to increase hit targets.
-
## Text
@@ -51,11 +37,6 @@ Note that `font` should be applied on a per element basis rather than globally s
```
-Type scales include: UI, Body, Heading, Title, Detail, and Code. Each scale has a default and additional t-shirt sizes (e.g., `ui-sm`, `heading-2xl`, `code-xl`).
-
-
-
-
diff --git a/packages/dev/s2-docs/src/S2Colors.tsx b/packages/dev/s2-docs/src/S2Colors.tsx
index 946aa8eba13..e4dd8f5e457 100644
--- a/packages/dev/s2-docs/src/S2Colors.tsx
+++ b/packages/dev/s2-docs/src/S2Colors.tsx
@@ -1,135 +1,150 @@
+'use client';
+
import {colorSwatch, getColorScale} from './color.macro' with {type: 'macro'};
import {Disclosure, DisclosurePanel, DisclosureTitle} from '@react-spectrum/s2';
import React from 'react';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
-export function S2Colors() {
+export function BackgroundColorsDisclosure() {
+ return (
+
+ Background colors
+
+ The backgroundColor property supports the following values, in addition to the semantic and global colors. These colors are specifically chosen to be used as backgrounds, so prefer them over global colors where possible.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export function TextColorsDisclosure() {
+ return (
+
+ Text colors
+
+ The color property supports the following values, in addition to the semantic and global colors. These colors are specifically chosen to be used as text colors, so prefer them over global colors where possible.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export function SemanticColorsDisclosure() {
+ return (
+
+ Semantic colors
+
+ The following values are available across all color properties. Prefer to use semantic colors over global colors when they represent a specific meaning.
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export function GlobalColorsDisclosure() {
return (
- <>
-
- Background colors
-
- The backgroundColor property supports the following values, in addition to the semantic and global colors shown below. These colors are specifically chosen to be used as backgrounds, so prefer them over global colors where possible.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Text colors
-
- The color property supports the following values, in addition to the semantic and global colors shown below. These colors are specifically chosen to be used as text colors, so prefer them over global colors where possible.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Semantic colors
-
- The following values are available across all color properties. Prefer to use semantic colors over global colors when they represent a specific meaning.
-
-
-
-
-
-
-
-
-
-
- Global colors
-
- The following values are available across all color properties.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
+
+ Global colors
+
+ The following values are available across all color properties.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
}
diff --git a/packages/dev/s2-docs/src/S2Typography.tsx b/packages/dev/s2-docs/src/S2Typography.tsx
index b490cda231b..eeff8cafa67 100644
--- a/packages/dev/s2-docs/src/S2Typography.tsx
+++ b/packages/dev/s2-docs/src/S2Typography.tsx
@@ -1,3 +1,5 @@
+'use client';
+
import React from 'react';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
diff --git a/packages/dev/s2-docs/src/styleProperties.ts b/packages/dev/s2-docs/src/styleProperties.ts
index 7df98cc25ab..ad1e6501f16 100644
--- a/packages/dev/s2-docs/src/styleProperties.ts
+++ b/packages/dev/s2-docs/src/styleProperties.ts
@@ -413,7 +413,7 @@ const shorthandMapping: {[key: string]: {values: string[], mapping: string[]}} =
mapping: ['overflowX', 'overflowY', 'textOverflow', 'whiteSpace']
},
font: {
- values: ['fontSize'],
+ values: [...fontSize],
mapping: ['fontFamily', 'fontSize', 'fontWeight', 'lineHeight', 'color']
}
};
@@ -465,18 +465,6 @@ export const spacingTypeValues = {
negativeSpacing: negativeBaseSpacingValues
};
-// a mapping of value to relative links that should be replaced in place
-// opted NOT to link to Fonts from 'ui', 'code', etc since the visual example
-// is so close to the area in the table where those are rendered
-const relativeLinks: {[key: string]: string} = {
- 'text-to-control': '#dimensions',
- 'text-to-visual': '#dimensions',
- 'edge-to-text': '#dimensions',
- 'pill': '#dimensions',
- 'baseColors': '#colors',
- 'fontSize': '#text'
-};
-
// a mapping of value to mdn links that should be replaced in place
const mdnTypeLinks: {[key: string]: string} = {
'string': 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String',
@@ -546,8 +534,6 @@ export function getPropertyDefinitions(propertyCategory: string): {[key: string]
if (mdnTypeLinks[value]) {
links[value] = {href: mdnTypeLinks[value]};
- } else if (relativeLinks[value]) {
- links[value] = {href: relativeLinks[value], isRelative: true};
}
}
}
@@ -576,8 +562,6 @@ export function getShorthandDefinitions(): {[key: string]: StyleMacroPropertyDef
if (mdnTypeLinks[value]) {
links[value] = {href: mdnTypeLinks[value]};
- } else if (relativeLinks[value]) {
- links[value] = {href: relativeLinks[value], isRelative: true};
}
}
diff --git a/packages/dev/s2-docs/src/types.tsx b/packages/dev/s2-docs/src/types.tsx
index 015c5f53727..d9295b9278d 100644
--- a/packages/dev/s2-docs/src/types.tsx
+++ b/packages/dev/s2-docs/src/types.tsx
@@ -10,12 +10,15 @@
* governing permissions and limitations under the License.
*/
+import {Accordion, Disclosure, DisclosurePanel, DisclosureTitle} from '@react-spectrum/s2';
import Asterisk from '../../../@react-spectrum/s2/ui-icons/Asterisk';
+import {BackgroundColorsDisclosure, GlobalColorsDisclosure, SemanticColorsDisclosure, TextColorsDisclosure} from './S2Colors';
import {Code, styles as codeStyles} from './Code';
import {ColorLink, Link as SpectrumLink} from './Link';
import {getDoc} from 'globals-docs';
import Markdown from 'markdown-to-jsx';
import React, {ReactNode} from 'react';
+import {S2Typography} from './S2Typography';
import {spacingTypeValues} from './styleProperties';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {Table, TableBody, TableCell, TableColumn, TableHeader, TableRow} from './Table';
@@ -696,7 +699,7 @@ function TemplateLiteral({elements}: TTemplate) {
);
}
-const styleMacroTypeLinks = {
+const styleMacroValueDesc = {
'baseSpacing': {
description: 'Base spacing values in pixels, following a 4px grid. Will be converted to rem.',
body: (
@@ -723,6 +726,48 @@ const styleMacroTypeLinks = {
)
},
+ 'text-to-control': {
+ description: 'Default spacing between text and a control (e.g., label and input). Scales with font size.'
+ },
+ 'text-to-visual': {
+ description: 'Default spacing between text and a visual element (e.g., icon). Scales with font size.'
+ },
+ 'edge-to-text': {
+ description: 'Default spacing between the edge of a control and its text. Relative to control height.'
+ },
+ 'pill': {
+ description: 'Default spacing between the edge of a pill-shaped control and its text. Relative to control height.'
+ },
+ 'baseColors': {
+ description: <>baseColors consists of the following values below:>,
+ body: (
+ <>
+
+
+ >
+ )
+ },
+ 'fontSize': {
+ body:
+ },
+ 'ui': {
+ description: 'Use within interactive UI components.'
+ },
+ 'heading': {
+ description: 'Use for headings in content pages.'
+ },
+ 'title': {
+ description: 'Use for titles within UI components such as cards or panels.'
+ },
+ 'body': {
+ description: 'Use for the content of pages that are primarily text.'
+ },
+ 'detail': {
+ description: 'Use for less important metadata.'
+ },
+ 'code': {
+ description: 'Use for source code.'
+ },
'LengthPercentage': {
description: <>A CSS length value with percentage or viewport units. e.g. '50%', '100vw', '50vh'>
},
@@ -731,26 +776,6 @@ const styleMacroTypeLinks = {
}
};
-interface StyleMacroTypePopoverProps {
- typeName: string,
- description: ReactNode,
- body?: ReactNode,
- link?: string
-}
-
-function StyleMacroTypePopover({typeName, description, body}: StyleMacroTypePopoverProps) {
- return (
-
- <>
-
- {description}
-
- {body}
- >
-
- );
-}
-
interface StyleMacroPropertyDefinition {
values: string[],
additionalTypes?: string[],
@@ -765,94 +790,182 @@ interface StyleMacroPropertiesProps {
export function StyleMacroProperties({properties}: StyleMacroPropertiesProps) {
let propertyNames = Object.keys(properties);
- let hasMapping = Object.values(properties).some(p => p.mapping);
return (
-
-
-
- Property
- Values
- {hasMapping && Mapping}
-
-
-
- {propertyNames.map((propertyName, index) => {
- let propDef = properties[propertyName];
- let values = propDef.values;
- let links = propDef.links || {};
-
- return (
-
-
-
-
- {propertyName}
-
-
-
-
- {values.map((value, i) => (
-
- {i > 0 && {' | '}}
- {links[value] ? (
-
- {value}
-
- ) : (
- '{value}'
+
+ {propertyNames.map((propertyName, index) => {
+ let propDef = properties[propertyName];
+ let values = propDef.values;
+ let links = propDef.links || {};
+
+ return (
+
+
+
+ {propertyName}
+
+
+
+
+ {/* for color and backgroundColor, skip values list and render disclosures directly since the contents of the disclosures cover the mapped values */}
+ {(() => {
+ if (propertyName === 'color') {
+ return (
+
+
+ {styleMacroValueDesc['baseColors'].body}
+
+ );
+ }
+ if (propertyName === 'backgroundColor') {
+ return (
+
+
+ {styleMacroValueDesc['baseColors'].body}
+
+ );
+ }
+ return (
+
+
Values
+
+ {values.map((value, i) => {
+ let content;
+ if (links[value]) {
+ content = (
+
+ {value}
+
+ );
+ } else if (value === 'baseColors') {
+ content = {value};
+ } else {
+ content = '{value}';
+ }
+
+ return (
+
+ {i > 0 && {' | '}}
+ {content}
+
+ );
+ })}
+ {/* for additional types properties (e.g. properties that have negative spacing or accept number/length percentage) we add them to the end */}
+ {propDef.additionalTypes && propDef.additionalTypes.map((typeName, i) => {
+ return (
+
+ {(values.length > 0 || i > 0) && {' | '}}
+ {typeName}
+
+ );
+ })}
+
+
+ );
+ })()}
+ {values.map((value, i) => {
+ let valueDesc = styleMacroValueDesc[value];
+ // special case handling for font and spacing specific value descriptions so they don't get rendered for
+ // other properties that may include the same values (e.g. heading in Colors)
+ // skip baseColors here as it will be rendered after
+ let shouldShowDescription = false;
+ if (value === 'fontSize' && (propertyName === 'fontSize' || propertyName === 'font')) {
+ shouldShowDescription = true;
+ } else if (['ui', 'heading', 'title', 'body', 'detail', 'code'].includes(value) && propertyName === 'lineHeight') {
+ shouldShowDescription = true;
+ } else if (['text-to-control', 'text-to-visual', 'edge-to-text', 'pill'].includes(value)) {
+ shouldShowDescription = true;
+ }
+
+ if (shouldShowDescription && (valueDesc?.description || valueDesc?.body)) {
+ return (
+
+
+
+ '{value}'
+
+
+ {valueDesc.description && (
+
+ {valueDesc.description}
+
)}
-
- ))}
- {propDef.additionalTypes && propDef.additionalTypes.map((typeName, i) => {
- let typeLink = styleMacroTypeLinks[typeName];
- return (
-
- {(values.length > 0 || i > 0) && {' | '}}
- {/* eslint-disable-next-line no-nested-ternary */}
- {typeLink ? (
- // only if the type link has a description and/or body do we want to render the type popover
- // this is to make things like baseColor
- typeLink.link && !typeLink.description && !typeLink.body ? (
- {typeName}
- ) : (
-
- )
- ) : undefined}
-
- );
- })}
-
-
- {hasMapping && (
-
+ {valueDesc.body}
+
+ );
+ }
+ return null;
+ })}
+ {/* show S2Typography for "fontSize" property and "font" shorthand specificatlly */}
+ {(propertyName === 'fontSize' || propertyName === 'font') && (
+
+ )}
+ {/* for other color property names show baseColors description since the value list is displayed still */}
+ {values.includes('baseColors') && styleMacroValueDesc['baseColors'] && (propertyName !== 'color' && propertyName !== 'backgroundColor') && (
+
+ {styleMacroValueDesc['baseColors'].description && (
+
+ {styleMacroValueDesc['baseColors'].description}
+
+ )}
+ {styleMacroValueDesc['baseColors'].body}
+
+ )}
+ {/* for the types that have descriptions, we add them below with the associated descriptions and/or mappings */}
+ {propDef.additionalTypes && propDef.additionalTypes.map((typeName, i) => {
+ let typeLink = styleMacroValueDesc[typeName];
+ if (typeLink?.description || typeLink?.body) {
+ // dont render the type name for properties that only have one special value (e.g. baseSpacing) that has an associated description
+ // so that we don't double up on rendering the value name
+ let shouldSkipTypeName = values.length === 0 && propDef.additionalTypes?.length === 1;
+
+ return (
+
+ {!shouldSkipTypeName && (
+
+
+ {typeName}
+
+
+ )}
+ {typeLink.description && (
+
+ {typeLink.description}
+
+ )}
+ {typeLink.body}
+
+ );
+ }
+ return null;
+ })}
+ {propDef.mapping && (
+
+
Maps to
- {propDef.mapping?.map((mappedProp, i) => (
+ {propDef.mapping.map((mappedProp, i) => (
{i > 0 && {', '}}
{mappedProp}
))}
-
+
)}
-
- {propDef.description && (
-
- {propDef.description}
-
- )}
-
- );
- })}
-
-
+ {propDef.description && (
+
+ {propDef.description}
+
+ )}
+
+
+
+ );
+ })}
+
);
}