diff --git a/packages/gamut-styles/src/variance/config.ts b/packages/gamut-styles/src/variance/config.ts index 4ba51362f45..c76f30fba04 100644 --- a/packages/gamut-styles/src/variance/config.ts +++ b/packages/gamut-styles/src/variance/config.ts @@ -245,6 +245,21 @@ export const margin = { mb: { property: 'marginBottom', scale: 'spacing' }, mr: { property: 'marginRight', scale: 'spacing' }, ml: { property: 'marginLeft', scale: 'spacing' }, + // Logical properties + mbl: { + property: 'margin', + properties: ['marginBlockStart', 'marginBlockEnd'], + scale: 'spacing', + }, + mbls: { property: 'marginBlockStart', scale: 'spacing' }, + mble: { property: 'marginBlockEnd', scale: 'spacing' }, + mi: { + property: 'margin', + properties: ['marginInlineStart', 'marginInlineEnd'], + scale: 'spacing', + }, + mis: { property: 'marginInlineStart', scale: 'spacing' }, + mie: { property: 'marginInlineEnd', scale: 'spacing' }, } as const; export const padding = { @@ -263,6 +278,21 @@ export const padding = { pb: { property: 'paddingBottom', scale: 'spacing' }, pr: { property: 'paddingRight', scale: 'spacing' }, pl: { property: 'paddingLeft', scale: 'spacing' }, + // Logical properties + pbl: { + property: 'padding', + properties: ['paddingBlockStart', 'paddingBlockEnd'], + scale: 'spacing', + }, + pbls: { property: 'paddingBlockStart', scale: 'spacing' }, + pble: { property: 'paddingBlockEnd', scale: 'spacing' }, + pi: { + property: 'padding', + properties: ['paddingInlineStart', 'paddingInlineEnd'], + scale: 'spacing', + }, + pis: { property: 'paddingInlineStart', scale: 'spacing' }, + pie: { property: 'paddingInlineEnd', scale: 'spacing' }, } as const; export const space = { diff --git a/packages/styleguide/src/lib/Foundations/System/Props/Space.mdx b/packages/styleguide/src/lib/Foundations/System/Props/Space.mdx index 0afcbb48e6a..cae665e79af 100644 --- a/packages/styleguide/src/lib/Foundations/System/Props/Space.mdx +++ b/packages/styleguide/src/lib/Foundations/System/Props/Space.mdx @@ -1,8 +1,9 @@ -import { Meta } from '@storybook/blocks'; +import { Canvas, Meta } from '@storybook/blocks'; import { AboutHeader, TokenTable } from '~styleguide/blocks'; import { defaultColumns, getPropRows } from '../../shared/elements'; +import * as SpaceStories from './Space.stories'; export const parameters = { title: 'Space', @@ -10,7 +11,7 @@ export const parameters = { status: 'updating', }; - + @@ -25,4 +26,20 @@ const SpaceExample = styled.div(system.space); ; ``` +## Logical Properties + +Logical spacing properties like `mbl` (marginBlock) provide RTL-aware spacing that adapts to text direction. The `mbl` prop applies margin to both block start and block end, which in LTR layouts is equivalent to margin-top and margin-bottom. + +### `mbl` (marginBlock) + + + +### `mi` (marginInline) + +The `mi` prop applies margin to both inline start and inline end, which in LTR layouts is equivalent to margin-left and margin-right. + + + + + diff --git a/packages/styleguide/src/lib/Foundations/System/Props/Space.stories.tsx b/packages/styleguide/src/lib/Foundations/System/Props/Space.stories.tsx new file mode 100644 index 00000000000..7cf05b28909 --- /dev/null +++ b/packages/styleguide/src/lib/Foundations/System/Props/Space.stories.tsx @@ -0,0 +1,206 @@ +import { + Box, + FlexBox, + FormGroup, + Radio, + RadioGroup, + Text, +} from '@codecademy/gamut'; +import type { Meta, StoryObj } from '@storybook/react'; +import { ChangeEvent, useState } from 'react'; + +const meta: Meta = { + title: 'Foundations/System/Props/Space', + component: Box, +}; + +export default meta; +type Story = StoryObj; + +export const MarginBlock: Story = { + render: () => ( + + + This box has mbl={32} (marginBlock), which applies margin + to both block start and block end. In LTR, this is equivalent to + margin-top and margin-bottom. + + + + This box uses my={32} for comparison. Notice how the + logical property mbl provides the same visual result but is + RTL-aware. + + + ), +}; + +export const MarginInline: Story = { + render: () => ( + + + + This box has mi={32} (marginInline), which applies margin + to both inline start and inline end. In LTR, this is equivalent to + margin-left and margin-right. + + + This box uses mx={32} for comparison. Notice how the + logical property mi provides the same visual result but + is RTL-aware. + + + + ), +}; + +export const RTLComparison: Story = { + render: () => { + const Component = () => { + const [direction, setDirection] = useState<'ltr' | 'rtl'>('ltr'); + const [writingMode, setWritingMode] = useState< + 'horizontal-tb' | 'vertical-rl' | 'vertical-lr' + >('horizontal-tb'); + + return ( + + {/* Controls */} + + + + ) => { + setDirection(event.target.value as 'ltr' | 'rtl'); + }} + > + + + + + + + + ) => { + setWritingMode( + event.target.value as + | 'horizontal-tb' + | 'vertical-rl' + | 'vertical-lr' + ); + }} + > + + + + + + + + + {/* Demo Container */} + + + {direction === 'ltr' ? 'LTR' : 'RTL'} ({writingMode}) + + + + + + + marginInlineStart={48} + + Logical property +
+ + Margin on start (adapts to direction & writing mode) + +
+
+ + + + + marginLeft={48} + + Physical property +
+ + Margin on left (always fixed) + +
+
+
+
+
+ + + Notice: + {' '} + marginInlineStart adapts to direction and writing mode,{' '} + marginLeft stays fixed + +
+ ); + }; + return ; + }, +};