-
-
Notifications
You must be signed in to change notification settings - Fork 11.5k
Added Shade layout primitives #27180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
4662aa4
e6fe8fd
6cf1c5b
9bf98b3
d6b1f0e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| import type {Meta, StoryObj} from '@storybook/react-vite'; | ||
| import {Box} from './box'; | ||
|
|
||
| const meta = { | ||
| title: 'Primitives / Box', | ||
| component: Box, | ||
| tags: ['autodocs'], | ||
| parameters: { | ||
| docs: { | ||
| description: { | ||
| component: 'Framing primitive for padding and radius without implicit layout behavior.' | ||
| } | ||
| } | ||
| } | ||
| } satisfies Meta<typeof Box>; | ||
|
|
||
| export default meta; | ||
| type Story = StoryObj<typeof Box>; | ||
|
|
||
| export const Default: Story = { | ||
| args: { | ||
| padding: 'lg', | ||
| radius: 'lg', | ||
| className: 'border border-border-default bg-surface-panel', | ||
| children: 'Framed content' | ||
| } | ||
| }; | ||
|
|
||
| export const AxisPadding: Story = { | ||
| args: { | ||
| paddingX: 'xl', | ||
| paddingY: 'sm', | ||
| radius: 'md', | ||
| className: 'border border-border-default bg-surface-panel', | ||
| children: 'Independent horizontal and vertical spacing' | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| import {cn} from '@/lib/utils'; | ||
| import {PADDING_CLASSES, PADDING_X_CLASSES, PADDING_Y_CLASSES, SpaceStep} from './types'; | ||
| import React from 'react'; | ||
|
|
||
| type BoxRadius = 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full'; | ||
|
|
||
| const RADIUS_CLASSES: Record<BoxRadius, string> = { | ||
| none: 'rounded-none', | ||
| sm: 'rounded-sm', | ||
| md: 'rounded-md', | ||
| lg: 'rounded-lg', | ||
| xl: 'rounded-xl', | ||
| full: 'rounded-full' | ||
| }; | ||
|
|
||
| export interface BoxProps extends React.HTMLAttributes<HTMLDivElement> { | ||
| padding?: SpaceStep; | ||
| paddingX?: SpaceStep; | ||
| paddingY?: SpaceStep; | ||
| radius?: BoxRadius; | ||
| } | ||
|
|
||
| function Box({ | ||
| className, | ||
| padding, | ||
| paddingX, | ||
| paddingY, | ||
| radius, | ||
| ...props | ||
| }: BoxProps) { | ||
|
Check warning on line 30 in apps/shade/src/components/primitives/box.tsx
|
||
| return ( | ||
| <div | ||
| className={cn( | ||
| padding && PADDING_CLASSES[padding], | ||
| paddingX && PADDING_X_CLASSES[paddingX], | ||
| paddingY && PADDING_Y_CLASSES[paddingY], | ||
| radius && RADIUS_CLASSES[radius], | ||
| className | ||
| )} | ||
| {...props} | ||
| /> | ||
| ); | ||
| } | ||
|
|
||
| export {Box}; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| import type {Meta, StoryObj} from '@storybook/react-vite'; | ||
| import {Container} from './container'; | ||
|
|
||
| const meta = { | ||
| title: 'Primitives / Container', | ||
| component: Container, | ||
| tags: ['autodocs'], | ||
| parameters: { | ||
| layout: 'fullscreen', | ||
| docs: { | ||
| description: { | ||
| component: 'Width-constrained primitive for page and region containers.' | ||
| } | ||
| } | ||
| } | ||
| } satisfies Meta<typeof Container>; | ||
|
|
||
| export default meta; | ||
| type Story = StoryObj<typeof Container>; | ||
|
|
||
| export const PageWidth: Story = { | ||
| args: { | ||
| size: 'page', | ||
| paddingX: 'lg', | ||
| children: ( | ||
| <div className="rounded-md border border-border-default bg-surface-panel p-4"> | ||
| Page-width container content | ||
| </div> | ||
| ) | ||
| }, | ||
| render: args => ( | ||
| <div className="w-full bg-accent py-6"> | ||
| <Container {...args} /> | ||
| </div> | ||
| ) | ||
| }; | ||
|
|
||
| export const ProseWidth: Story = { | ||
| args: { | ||
| size: 'prose', | ||
| centered: true, | ||
| children: ( | ||
| <div className="rounded-md border border-border-default bg-surface-panel p-4 text-sm"> | ||
| A narrower, readable content width intended for copy-heavy regions. | ||
| </div> | ||
| ) | ||
| }, | ||
| render: args => ( | ||
| <div className="w-full bg-accent py-6"> | ||
| <Container {...args} /> | ||
| </div> | ||
| ) | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| import {cn} from '@/lib/utils'; | ||
| import {PADDING_X_CLASSES, SpaceStep} from './types'; | ||
| import React from 'react'; | ||
|
|
||
| export type ContainerSize = | ||
| | 'xs' | ||
| | 'sm' | ||
| | 'md' | ||
| | 'lg' | ||
| | 'xl' | ||
| | '2xl' | ||
| | '3xl' | ||
| | '4xl' | ||
| | '5xl' | ||
| | '6xl' | ||
| | '7xl' | ||
| | '8xl' | ||
| | '9xl' | ||
| | 'prose' | ||
| | 'page' | ||
| | 'page-with-sidebar'; | ||
|
|
||
| const MAX_WIDTH_CLASSES: Record<ContainerSize, string> = { | ||
| xs: 'max-w-xs', | ||
| sm: 'max-w-sm', | ||
| md: 'max-w-md', | ||
| lg: 'max-w-lg', | ||
| xl: 'max-w-xl', | ||
| '2xl': 'max-w-2xl', | ||
| '3xl': 'max-w-3xl', | ||
| '4xl': 'max-w-4xl', | ||
| '5xl': 'max-w-5xl', | ||
| '6xl': 'max-w-6xl', | ||
| '7xl': 'max-w-7xl', | ||
| '8xl': 'max-w-8xl', | ||
| '9xl': 'max-w-9xl', | ||
| prose: 'max-w-prose', | ||
| page: 'max-w-page', | ||
| 'page-with-sidebar': 'max-w-pageminsidebar' | ||
| }; | ||
|
|
||
| export interface ContainerProps extends React.HTMLAttributes<HTMLDivElement> { | ||
| size?: ContainerSize; | ||
| centered?: boolean; | ||
| paddingX?: SpaceStep; | ||
| } | ||
|
|
||
| function Container({ | ||
| className, | ||
| size = 'page', | ||
| centered = true, | ||
| paddingX, | ||
| ...props | ||
| }: ContainerProps) { | ||
|
Check warning on line 54 in apps/shade/src/components/primitives/container.tsx
|
||
| return ( | ||
| <div | ||
| className={cn( | ||
| 'w-full', | ||
| MAX_WIDTH_CLASSES[size], | ||
| centered && 'mx-auto', | ||
| paddingX && PADDING_X_CLASSES[paddingX], | ||
| className | ||
| )} | ||
| {...props} | ||
| /> | ||
| ); | ||
| } | ||
|
|
||
| export {Container}; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| import type {Meta, StoryObj} from '@storybook/react-vite'; | ||
| import {Grid} from './grid'; | ||
|
|
||
| const meta = { | ||
| title: 'Primitives / Grid', | ||
| component: Grid, | ||
| tags: ['autodocs'], | ||
| parameters: { | ||
| docs: { | ||
| description: { | ||
| component: 'Two-dimensional layout primitive for explicit columns and spacing.' | ||
| } | ||
| } | ||
| } | ||
| } satisfies Meta<typeof Grid>; | ||
|
|
||
| export default meta; | ||
| type Story = StoryObj<typeof Grid>; | ||
|
|
||
| const renderCell = (label: string) => ( | ||
| <div className="rounded-md border border-border-default bg-surface-panel p-3 text-sm"> | ||
| {label} | ||
| </div> | ||
| ); | ||
|
|
||
| export const TwoColumns: Story = { | ||
| args: { | ||
| columns: 2, | ||
| gap: 'md', | ||
| children: ( | ||
| <> | ||
| {renderCell('Card 1')} | ||
| {renderCell('Card 2')} | ||
| {renderCell('Card 3')} | ||
| {renderCell('Card 4')} | ||
| </> | ||
| ) | ||
| } | ||
| }; | ||
|
|
||
| export const ThreeColumns: Story = { | ||
| args: { | ||
| columns: 3, | ||
| gap: 'lg', | ||
| children: ( | ||
| <> | ||
| {renderCell('A')} | ||
| {renderCell('B')} | ||
| {renderCell('C')} | ||
| {renderCell('D')} | ||
| {renderCell('E')} | ||
| {renderCell('F')} | ||
| </> | ||
| ) | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| import {cn} from '@/lib/utils'; | ||
| import { | ||
| ALIGN_ITEMS_CLASSES, | ||
| GAP_CLASSES, | ||
| JUSTIFY_CONTENT_CLASSES, | ||
| Align, | ||
| Justify, | ||
| SpaceStep | ||
| } from './types'; | ||
| import React from 'react'; | ||
|
|
||
| type GridColumns = 1 | 2 | 3 | 4 | 5 | 6 | 12; | ||
|
|
||
| const GRID_COLUMNS_CLASSES: Record<GridColumns, string> = { | ||
| 1: 'grid-cols-1', | ||
| 2: 'grid-cols-2', | ||
| 3: 'grid-cols-3', | ||
| 4: 'grid-cols-4', | ||
| 5: 'grid-cols-5', | ||
| 6: 'grid-cols-6', | ||
| 12: 'grid-cols-12' | ||
| }; | ||
|
|
||
| export interface GridProps extends React.HTMLAttributes<HTMLDivElement> { | ||
| columns?: GridColumns; | ||
| gap?: SpaceStep; | ||
| align?: Align; | ||
| justify?: Justify; | ||
| } | ||
|
|
||
| function Grid({ | ||
| className, | ||
| columns = 1, | ||
| gap = 'md', | ||
| align = 'stretch', | ||
| justify = 'start', | ||
| ...props | ||
| }: GridProps) { | ||
|
Check warning on line 38 in apps/shade/src/components/primitives/grid.tsx
|
||
| return ( | ||
| <div | ||
| className={cn( | ||
| 'grid', | ||
| GRID_COLUMNS_CLASSES[columns], | ||
| GAP_CLASSES[gap], | ||
| ALIGN_ITEMS_CLASSES[align], | ||
| JUSTIFY_CONTENT_CLASSES[justify], | ||
| className | ||
| )} | ||
| {...props} | ||
| /> | ||
| ); | ||
| } | ||
|
|
||
| export {Grid}; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| export {Box} from './box'; | ||
| export {Container} from './container'; | ||
| export type {ContainerSize} from './container'; | ||
| export {Grid} from './grid'; | ||
| export {Inline} from './inline'; | ||
| export {Stack} from './stack'; | ||
| export {Text} from './text'; | ||
| export type { | ||
| TextElement, | ||
| TextLeading, | ||
| TextSize, | ||
| TextTone, | ||
| TextWeight | ||
| } from './text'; | ||
| export type {Align, Justify, SpaceStep} from './types'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the
@alias for internal primitive imports.Line 2 should use the project alias instead of a relative internal import.
Suggested change
As per coding guidelines:
apps/shade/src/**/*.{ts,tsx,js}: Use the@alias for internal imports (e.g.@/lib/utils).📝 Committable suggestion
🤖 Prompt for AI Agents