A design system in a box. hip-ui.tngl.io/docs/introduction
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

remove unused example

-7120
-7
apps/example/.gitignore
··· 1 - node_modules 2 - dist 3 - .env* 4 - *.tsbuildinfo 5 - .cache 6 - .DS_Store 7 - *.pem
-4
apps/example/hip.config.json
··· 1 - { 2 - "componentDir": "src/components", 3 - "packageManager": "pnpm" 4 - }
-32
apps/example/package.json
··· 1 - { 2 - "name": "example2", 3 - "version": "0.0.0", 4 - "type": "module", 5 - "private": true, 6 - "scripts": { 7 - "dev": "waku dev", 8 - "build": "waku build", 9 - "start": "waku start" 10 - }, 11 - "dependencies": { 12 - "@react-stately/utils": "catalog:", 13 - "@react-types/overlays": "catalog:", 14 - "@repo/typescript-config": "workspace:*", 15 - "@stylexjs/stylex": "catalog:", 16 - "hip-ui": "workspace:*", 17 - "lucide-react": "catalog:", 18 - "react": "catalog:", 19 - "react-aria": "catalog:", 20 - "react-aria-components": "catalog:", 21 - "react-dom": "catalog:", 22 - "react-server-dom-webpack": "catalog:", 23 - "react-stately": "catalog:", 24 - "unplugin-stylex": "^0.5.5", 25 - "waku": "0.26.1" 26 - }, 27 - "devDependencies": { 28 - "@types/react": "catalog:", 29 - "@types/react-dom": "catalog:", 30 - "typescript": "catalog:" 31 - } 32 - }
apps/example/public/images/favicon.png

This is a binary file and will not be displayed.

-2
apps/example/public/robots.txt
··· 1 - User-agent: * 2 - Disallow: /RSC/
-937
apps/example/src/components/KitchenSink.tsx
··· 1 - "use client"; 2 - 3 - import * as stylex from "@stylexjs/stylex"; 4 - import { 5 - AlertDialog, 6 - AlertDialogFooter, 7 - } from "hip-ui/components/alert-dialog/index"; 8 - import { Avatar } from "hip-ui/components/avatar/index"; 9 - import { Badge } from "hip-ui/components/badge/index"; 10 - import { 11 - Dialog, 12 - DialogDescription, 13 - DialogFooter, 14 - DialogHeader, 15 - } from "hip-ui/components/dialog/index"; 16 - import { 17 - ArrowDown, 18 - ArrowLeft, 19 - ArrowRight, 20 - ArrowUp, 21 - AxeIcon, 22 - Check, 23 - Copy, 24 - CpuIcon, 25 - Ellipsis, 26 - File, 27 - Folder, 28 - GlobeIcon, 29 - Image, 30 - Info, 31 - Pin, 32 - Plus, 33 - Scissors, 34 - Star, 35 - } from "lucide-react"; 36 - 37 - import { Button } from "../components/button"; 38 - import { ButtonGroup } from "../components/button-group"; 39 - import { Flex } from "../components/flex"; 40 - import { TextField } from "../components/text-field"; 41 - import { Tooltip } from "../components/tooltip"; 42 - import { 43 - AlertDialogActionButton, 44 - AlertDialogCancelButton, 45 - AlertDialogDescription, 46 - AlertDialogHeader, 47 - } from "./alert-dialog"; 48 - import { 49 - Card, 50 - CardBody, 51 - CardDescription, 52 - CardFooter, 53 - CardHeader, 54 - CardTitle, 55 - } from "./card"; 56 - import { Checkbox, CheckboxGroup } from "./checkbox"; 57 - import { ColorField } from "./color-field"; 58 - import { ComboBox, ComboBoxItem } from "./combobox"; 59 - import { 60 - CommandMenu, 61 - CommandMenuItem, 62 - CommandMenuSection, 63 - CommandMenuSectionHeader, 64 - } from "./command-menu"; 65 - import { ContextMenu } from "./context-menu"; 66 - import { DateField } from "./date-field"; 67 - import { IconButton } from "./icon-button"; 68 - import { Link } from "./link"; 69 - import { 70 - Menu, 71 - MenuItem, 72 - MenuSection, 73 - MenuSectionHeader, 74 - MenuSeparator, 75 - SubMenu, 76 - } from "./menu"; 77 - import { NumberField } from "./number-field"; 78 - import { Popover } from "./popover"; 79 - import { Radio, RadioGroup } from "./radio"; 80 - import { SearchField } from "./search-field"; 81 - import { Select, SelectItem } from "./select"; 82 - import { Separator } from "./separator"; 83 - import { TextArea } from "./text-area"; 84 - import { slate } from "./theme/colors.stylex"; 85 - import { radius } from "./theme/radius.stylex"; 86 - import { gray } from "./theme/semantic-color.stylex"; 87 - import { spacing } from "./theme/spacing.stylex"; 88 - import { typeramp } from "./theme/typography.stylex"; 89 - import { TimeField } from "./time-field"; 90 - import { ToggleButton } from "./toggle-button"; 91 - import { ToggleButtonGroup } from "./toggle-button-group"; 92 - import { Tree, TreeItem } from "./tree"; 93 - import { 94 - Blockquote, 95 - Body, 96 - Heading1, 97 - Heading2, 98 - Heading3, 99 - Heading4, 100 - InlineCode, 101 - ListItem, 102 - OrderedList, 103 - SmallBody, 104 - SubLabel, 105 - UnorderedList, 106 - } from "./typography"; 107 - 108 - const styles = stylex.create({ 109 - capitalize: { 110 - textTransform: "capitalize", 111 - }, 112 - subCard: { 113 - padding: spacing["4"], 114 - }, 115 - container: { 116 - padding: spacing["16"], 117 - }, 118 - buttonLabel: { 119 - textTransform: "capitalize", 120 - width: 80, 121 - }, 122 - signUpForm: { 123 - padding: spacing["2"], 124 - width: 300, 125 - }, 126 - grow: { 127 - flexGrow: 1, 128 - }, 129 - contextMenuArea: { 130 - padding: spacing["4"], 131 - borderColor: slate.border2, 132 - borderRadius: radius["md"], 133 - borderStyle: "solid", 134 - borderWidth: 1, 135 - backgroundColor: slate.component1, 136 - height: "100px", 137 - width: "100px", 138 - }, 139 - }); 140 - 141 - function Typography() { 142 - return ( 143 - <Flex direction="column" gap="4"> 144 - <Heading1>Heading 1</Heading1> 145 - <Body> 146 - This is a body text. You can use <InlineCode>InlineCode</InlineCode> to 147 - highlight code. 148 - </Body> 149 - <Blockquote>This is a blockquote.</Blockquote> 150 - <Heading2>Heading 2</Heading2> 151 - <Body>This is a body text.</Body> 152 - <UnorderedList> 153 - <ListItem>This is a list item.</ListItem> 154 - <ListItem>This is a list item.</ListItem> 155 - <ListItem>This is a list item.</ListItem> 156 - </UnorderedList> 157 - <Body>This is a body text.</Body> 158 - <Heading3>Heading 3</Heading3> 159 - <Body>This is a body text.</Body> 160 - <OrderedList> 161 - <ListItem>This is a list item.</ListItem> 162 - <ListItem>This is a list item.</ListItem> 163 - </OrderedList> 164 - <Heading4>Heading 4</Heading4> 165 - </Flex> 166 - ); 167 - } 168 - 169 - const buttons = [ 170 - "primary", 171 - "secondary", 172 - "tertiary", 173 - "outline", 174 - "critical", 175 - ] as const; 176 - const buttonSizes = ["sm", "md", "lg"] as const; 177 - 178 - function Buttons() { 179 - return ( 180 - <Flex direction="column" gap="4"> 181 - {buttons.map((button) => ( 182 - <Flex key={button} align="center" gap="2"> 183 - <SmallBody style={[styles.buttonLabel, gray.textDim]}> 184 - {button} 185 - </SmallBody> 186 - 187 - <Flex align="center" gap="8"> 188 - {buttonSizes.map((size) => ( 189 - <Flex align="center" gap="2" key={`${button}-${size}`}> 190 - <IconButton variant={button} label="Add Another" size={size}> 191 - <Plus /> 192 - </IconButton> 193 - <Button variant={button} size={size}> 194 - Button 195 - </Button> 196 - <Button variant={button} size={size}> 197 - <Plus /> 198 - Add Another 199 - </Button> 200 - <Button variant={button} size={size}> 201 - Next 202 - <ArrowRight /> 203 - </Button> 204 - <Button variant={button} isDisabled size={size}> 205 - Button 206 - </Button> 207 - </Flex> 208 - ))} 209 - </Flex> 210 - </Flex> 211 - ))} 212 - </Flex> 213 - ); 214 - } 215 - 216 - function ButtonGroups() { 217 - return ( 218 - <Flex direction="column" gap="4"> 219 - {buttons.map( 220 - (button) => 221 - button !== "critical" && ( 222 - <Flex align="center" gap="2" key={button}> 223 - <ButtonGroup> 224 - <IconButton variant={button} label="Previous"> 225 - <ArrowLeft /> 226 - </IconButton> 227 - </ButtonGroup> 228 - <ButtonGroup> 229 - <ToggleButton variant={button}> 230 - <Star /> 231 - </ToggleButton> 232 - <Button variant={button}>Button 1</Button> 233 - <Button variant={button}>Button 2</Button> 234 - <Button variant={button}>Button 3</Button> 235 - <Button variant={button}>Button 4</Button> 236 - <ToggleButtonGroup> 237 - <ToggleButton variant={button}>Toggle Button 1</ToggleButton> 238 - <ToggleButton variant={button}>Toggle Button 2</ToggleButton> 239 - <ToggleButton variant={button}>Toggle Button 3</ToggleButton> 240 - </ToggleButtonGroup> 241 - </ButtonGroup> 242 - <ButtonGroup> 243 - <Button variant={button}>Action</Button> 244 - <IconButton variant={button} label="More"> 245 - <Ellipsis /> 246 - </IconButton> 247 - </ButtonGroup> 248 - </Flex> 249 - ), 250 - )} 251 - 252 - <Flex gap="2"> 253 - {buttons.map((button) => ( 254 - <ButtonGroup orientation="vertical" key={`${button}-vertical`}> 255 - <IconButton label="Up" variant={button}> 256 - <ArrowUp /> 257 - </IconButton> 258 - <IconButton label="Down" variant={button}> 259 - <ArrowDown /> 260 - </IconButton> 261 - </ButtonGroup> 262 - ))} 263 - </Flex> 264 - </Flex> 265 - ); 266 - } 267 - 268 - function FormElements() { 269 - return ( 270 - <Flex gap="4"> 271 - {buttonSizes.map((size) => ( 272 - <Card key={`${size}-text-field`} style={styles.subCard}> 273 - <Flex direction="column" gap="6"> 274 - <TextField 275 - key={`${size}-text-field`} 276 - label="Text Field" 277 - description="Input Description" 278 - size={size} 279 - /> 280 - <Select 281 - label="Select" 282 - placeholder="Select" 283 - description="Select Description" 284 - size={size} 285 - > 286 - <SelectItem>Select 1</SelectItem> 287 - <SelectItem>Select 2</SelectItem> 288 - <SelectItem>Select 3</SelectItem> 289 - <SelectItem>Select 4</SelectItem> 290 - <SelectItem>Select 5</SelectItem> 291 - </Select> 292 - <CheckboxGroup 293 - label="Checkbox Group" 294 - description="Checkbox Group Description" 295 - size={size} 296 - > 297 - <Checkbox value="1">Checkbox 1</Checkbox> 298 - <Checkbox value="2" isDisabled> 299 - Checkbox 2 300 - </Checkbox> 301 - <Checkbox value="3" isIndeterminate> 302 - Checkbox 3 303 - </Checkbox> 304 - </CheckboxGroup> 305 - <RadioGroup 306 - label="Radio Group" 307 - description="Radio Group Description" 308 - size={size} 309 - > 310 - <Radio value="1">Radio 1</Radio> 311 - <Radio value="2">Radio 2</Radio> 312 - <Radio value="3">Radio 3</Radio> 313 - </RadioGroup> 314 - </Flex> 315 - </Card> 316 - ))} 317 - </Flex> 318 - ); 319 - } 320 - 321 - function SignUpForm() { 322 - return ( 323 - <Card style={styles.signUpForm}> 324 - <CardHeader> 325 - <CardTitle>Sign Up</CardTitle> 326 - </CardHeader> 327 - <CardBody> 328 - <Flex direction="column" gap="4"> 329 - <TextField label="Email Address" type="email" /> 330 - <TextField 331 - type="password" 332 - label={ 333 - <Flex justify="between" align="center"> 334 - <span>Password</span> 335 - <Link style={typeramp.sublabel}>Forgot Password?</Link> 336 - </Flex> 337 - } 338 - /> 339 - </Flex> 340 - </CardBody> 341 - <CardFooter> 342 - <Button variant="secondary">Create Account</Button> 343 - <Button>Sign In</Button> 344 - </CardFooter> 345 - </Card> 346 - ); 347 - } 348 - 349 - function TitleCard({ 350 - title, 351 - children, 352 - }: { 353 - title: string; 354 - children: React.ReactNode; 355 - }) { 356 - return ( 357 - <Card> 358 - <CardHeader> 359 - <CardTitle>{title}</CardTitle> 360 - </CardHeader> 361 - <CardBody>{children}</CardBody> 362 - </Card> 363 - ); 364 - } 365 - 366 - function TextFields() { 367 - return ( 368 - <Flex direction="column" gap="4"> 369 - <TextField label="Text Field" /> 370 - <TextField label="Text Field with Icon" prefix={<CpuIcon />} /> 371 - <TextField 372 - label="Text Field with Suffix" 373 - suffix={<SmallBody variant="secondary">suffix</SmallBody>} 374 - /> 375 - <TextField label="Text Field with Icon" suffix={<Check />} /> 376 - <SearchField label="Search Field" /> 377 - <ColorField label="Color Field" /> 378 - <NumberField 379 - label="Number Field" 380 - minValue={0} 381 - prefix={<CpuIcon />} 382 - defaultValue={1} 383 - /> 384 - <TimeField label="Time Field" /> 385 - <DateField label="Date Field" /> 386 - <ComboBox label="ComboBox" placeholder="Select an option"> 387 - <ComboBoxItem>ComboBox Item 1</ComboBoxItem> 388 - <ComboBoxItem prefix={<GlobeIcon />} suffix={<div>new</div>}> 389 - ComboBox Item 2 390 - </ComboBoxItem> 391 - <ComboBoxItem isDisabled>ComboBox Item 2</ComboBoxItem> 392 - <ComboBoxItem>ComboBox Item 3</ComboBoxItem> 393 - <ComboBoxItem prefix={<Plus />}> 394 - ComboBox Item 4 395 - <SubLabel variant="secondary"> 396 - This is a description for ComboBox Item 4 397 - </SubLabel> 398 - </ComboBoxItem> 399 - </ComboBox> 400 - </Flex> 401 - ); 402 - } 403 - 404 - function Checkboxes() { 405 - return ( 406 - <Flex direction="column" gap="4"> 407 - <Checkbox>Accept terms and conditions</Checkbox> 408 - <Checkbox> 409 - <span>Accept terms and conditions</span> 410 - <SubLabel variant="secondary"> 411 - By clicking this box, you agree to our <Link>Terms of Service</Link>{" "} 412 - and <Link>Privacy Policy</Link>. 413 - </SubLabel> 414 - </Checkbox> 415 - </Flex> 416 - ); 417 - } 418 - 419 - function CheckboxGroups() { 420 - return ( 421 - <Flex direction="column" gap="4"> 422 - <CheckboxGroup 423 - label="Checkbox Group" 424 - description="Checkbox Group Description" 425 - > 426 - <Checkbox value="1">Checkbox 1</Checkbox> 427 - <Checkbox value="2" isDisabled> 428 - Checkbox 2 429 - </Checkbox> 430 - <Checkbox value="3" isIndeterminate> 431 - Checkbox 3 432 - </Checkbox> 433 - </CheckboxGroup> 434 - </Flex> 435 - ); 436 - } 437 - 438 - function Radios() { 439 - return ( 440 - <Flex direction="column" gap="4"> 441 - <RadioGroup label="Radio Group" description="Radio Group Description"> 442 - <Radio value="1">Radio 1</Radio> 443 - <Radio value="2">Radio 2</Radio> 444 - <Radio value="3">Radio 3</Radio> 445 - </RadioGroup> 446 - </Flex> 447 - ); 448 - } 449 - 450 - function PaymentMethod() { 451 - return ( 452 - <Card> 453 - <CardHeader> 454 - <CardTitle>Payment Method</CardTitle> 455 - <CardDescription>Select a payment method</CardDescription> 456 - </CardHeader> 457 - <CardBody> 458 - <Flex direction="column" gap="6"> 459 - <TextField label="Name on Card" placeholder="John Doe" /> 460 - <Flex direction="column" gap="3"> 461 - <Flex gap="3"> 462 - <TextField 463 - label="Card Number" 464 - placeholder="1234 5678 9012 3456" 465 - style={styles.grow} 466 - /> 467 - <TextField label="CVV" placeholder="123" style={styles.grow} /> 468 - </Flex> 469 - <SmallBody variant="secondary"> 470 - Enter your 16 digit number. 471 - </SmallBody> 472 - </Flex> 473 - <Flex gap="3"> 474 - <Select label="Month" placeholder="MM" style={styles.grow}> 475 - <SelectItem>01</SelectItem> 476 - <SelectItem>02</SelectItem> 477 - <SelectItem>03</SelectItem> 478 - <SelectItem>04</SelectItem> 479 - <SelectItem>05</SelectItem> 480 - <SelectItem>06</SelectItem> 481 - <SelectItem>07</SelectItem> 482 - <SelectItem>08</SelectItem> 483 - <SelectItem>09</SelectItem> 484 - <SelectItem>10</SelectItem> 485 - <SelectItem>11</SelectItem> 486 - <SelectItem>12</SelectItem> 487 - </Select> 488 - <Select label="Year" placeholder="YYYY" style={styles.grow}> 489 - <SelectItem>2025</SelectItem> 490 - <SelectItem>2026</SelectItem> 491 - <SelectItem>2027</SelectItem> 492 - <SelectItem>2028</SelectItem> 493 - <SelectItem>2029</SelectItem> 494 - </Select> 495 - </Flex> 496 - <Separator /> 497 - <Flex direction="column" gap="4"> 498 - <Flex direction="column" gap="3"> 499 - <CardTitle>Billing Address</CardTitle> 500 - <CardDescription> 501 - The billing address associated with your payment method 502 - </CardDescription> 503 - </Flex> 504 - <Checkbox>Same as shipping address</Checkbox> 505 - </Flex> 506 - <Separator /> 507 - <TextArea 508 - label="Message" 509 - placeholder="Add any additional comments" 510 - rows={4} 511 - /> 512 - <Flex gap="2"> 513 - <Button>Submit</Button> 514 - <Button variant="secondary">Cancel</Button> 515 - </Flex> 516 - </Flex> 517 - </CardBody> 518 - </Card> 519 - ); 520 - } 521 - 522 - function ToggleButtonGroups() { 523 - return ( 524 - <Flex direction="column" gap="4"> 525 - {buttons.map( 526 - (button) => 527 - button !== "critical" && ( 528 - <Flex key={button} gap="8"> 529 - {buttonSizes.map((size) => ( 530 - <ToggleButtonGroup 531 - key={`${button}-${size}`} 532 - selectionMode="single" 533 - > 534 - <ToggleButton 535 - variant={button} 536 - size={size} 537 - id={`${button}-${size}-1`} 538 - > 539 - Toggle Button 1 540 - </ToggleButton> 541 - <ToggleButton 542 - variant={button} 543 - size={size} 544 - id={`${button}-${size}-2`} 545 - > 546 - Toggle Button 2 547 - </ToggleButton> 548 - <ToggleButton 549 - variant={button} 550 - size={size} 551 - id={`${button}-${size}-3`} 552 - > 553 - Toggle Button 3 554 - </ToggleButton> 555 - </ToggleButtonGroup> 556 - ))} 557 - </Flex> 558 - ), 559 - )} 560 - </Flex> 561 - ); 562 - } 563 - 564 - function MenuExample() { 565 - return ( 566 - <Flex gap="2"> 567 - <Menu trigger={<Button>Click me</Button>}> 568 - <MenuItem>Menu Item 1</MenuItem> 569 - <MenuItem>Menu Item 2</MenuItem> 570 - <MenuItem>Menu Item 3</MenuItem> 571 - </Menu> 572 - <Menu 573 - trigger={ 574 - <IconButton label="More"> 575 - <Ellipsis /> 576 - </IconButton> 577 - } 578 - > 579 - <MenuSection> 580 - <MenuSectionHeader>Menu Section Header</MenuSectionHeader> 581 - <MenuItem>Menu Item 1</MenuItem> 582 - <MenuItem isDisabled>Menu Item 2</MenuItem> 583 - <MenuItem>Menu Item 3</MenuItem> 584 - </MenuSection> 585 - <MenuSeparator /> 586 - <MenuSection> 587 - <MenuSectionHeader>Menu Section 2</MenuSectionHeader> 588 - <MenuItem>Menu Item 4</MenuItem> 589 - <MenuItem>Menu Item 5</MenuItem> 590 - <SubMenu trigger={<MenuItem>Menu Item 6</MenuItem>}> 591 - <MenuItem>Menu Item 7</MenuItem> 592 - <MenuItem>Menu Item 8</MenuItem> 593 - <MenuItem>Menu Item 9</MenuItem> 594 - </SubMenu> 595 - </MenuSection> 596 - </Menu> 597 - 598 - <ContextMenu 599 - trigger={ 600 - <Flex 601 - style={styles.contextMenuArea} 602 - align="center" 603 - justify="center" 604 - {...stylex.props( 605 - typeramp.label, 606 - styles.contextMenuArea, 607 - gray.borderInteractive, 608 - )} 609 - > 610 - Right Click me 611 - </Flex> 612 - } 613 - > 614 - <MenuItem>Menu Item 1</MenuItem> 615 - <MenuItem>Menu Item 2</MenuItem> 616 - <MenuItem>Menu Item 3</MenuItem> 617 - </ContextMenu> 618 - </Flex> 619 - ); 620 - } 621 - 622 - function TreeExample() { 623 - return ( 624 - <> 625 - <Tree 626 - aria-label="Files" 627 - selectionMode="multiple" 628 - selectionBehavior="replace" 629 - defaultExpandedKeys={["documents", "photos", "project"]} 630 - > 631 - <TreeItem id="documents" title="Documents" prefix={<Folder />}> 632 - <TreeItem id="project" title="Project" prefix={<Folder />}> 633 - <TreeItem id="report" title="Weekly Report" prefix={<File />} /> 634 - </TreeItem> 635 - </TreeItem> 636 - <TreeItem id="photos" title="Photos" prefix={<Folder />}> 637 - <TreeItem id="one" title="Image 1" prefix={<Image />} /> 638 - <TreeItem id="two" title="Image 2" isDisabled prefix={<Image />} /> 639 - </TreeItem> 640 - <TreeItem 641 - id="three" 642 - title="Image 3" 643 - prefix={<Image />} 644 - suffix={ 645 - <Menu 646 - placement="right top" 647 - trigger={ 648 - <IconButton size="sm" variant="tertiary" label="More"> 649 - <Ellipsis /> 650 - </IconButton> 651 - } 652 - > 653 - <MenuItem>Menu Item 1</MenuItem> 654 - <MenuItem>Menu Item 2</MenuItem> 655 - <MenuItem>Menu Item 3</MenuItem> 656 - </Menu> 657 - } 658 - /> 659 - </Tree> 660 - </> 661 - ); 662 - } 663 - 664 - function CommandMenuExample() { 665 - return ( 666 - <Flex direction="column" gap="4"> 667 - <CommandMenu> 668 - <CommandMenuItem prefix={<AxeIcon />}>New</CommandMenuItem> 669 - <CommandMenuSection> 670 - <CommandMenuSectionHeader>Edit</CommandMenuSectionHeader> 671 - <CommandMenuItem 672 - prefix={<Copy />} 673 - onAction={() => console.log("Copy")} 674 - > 675 - Copy 676 - </CommandMenuItem> 677 - <CommandMenuItem prefix={<Plus />}>Paste</CommandMenuItem> 678 - <CommandMenuItem prefix={<Scissors />}>Cut</CommandMenuItem> 679 - <CommandMenuItem prefix={<Scissors />}>Cut</CommandMenuItem> 680 - <CommandMenuItem prefix={<Scissors />}>Cut</CommandMenuItem> 681 - <CommandMenuItem prefix={<Scissors />}>Cut</CommandMenuItem> 682 - <CommandMenuItem prefix={<Scissors />}>Cut</CommandMenuItem> 683 - <CommandMenuItem prefix={<Scissors />}>Cut</CommandMenuItem> 684 - <CommandMenuItem prefix={<Scissors />}>Cut</CommandMenuItem> 685 - <CommandMenuItem prefix={<Scissors />}>Cut</CommandMenuItem> 686 - </CommandMenuSection> 687 - </CommandMenu> 688 - </Flex> 689 - ); 690 - } 691 - 692 - function AlertDialogExample() { 693 - return ( 694 - <Flex direction="column" gap="4"> 695 - <AlertDialog trigger={<Button>Noraml Alert Dialog</Button>}> 696 - <AlertDialogHeader>Unauthenticated</AlertDialogHeader> 697 - <AlertDialogDescription> 698 - Please log in to continue. 699 - </AlertDialogDescription> 700 - <AlertDialogFooter> 701 - <AlertDialogActionButton>Log In</AlertDialogActionButton> 702 - </AlertDialogFooter> 703 - </AlertDialog> 704 - <AlertDialog trigger={<Button>Critical Alert Dialog</Button>}> 705 - <AlertDialogHeader>Critical Alert Dialog</AlertDialogHeader> 706 - <AlertDialogDescription> 707 - This action is critical and cannot be undone. 708 - </AlertDialogDescription> 709 - <AlertDialogFooter> 710 - <AlertDialogCancelButton /> 711 - <AlertDialogActionButton variant="critical"> 712 - Delete 713 - </AlertDialogActionButton> 714 - </AlertDialogFooter> 715 - </AlertDialog> 716 - </Flex> 717 - ); 718 - } 719 - 720 - function DialogExample() { 721 - return ( 722 - <Flex direction="column" gap="4"> 723 - <Dialog trigger={<Button>Click me</Button>}> 724 - <DialogHeader>Billing Information</DialogHeader> 725 - <DialogDescription> 726 - <Flex direction="column" gap="6"> 727 - <TextField label="Name on Card" placeholder="John Doe" /> 728 - <Flex direction="column" gap="3"> 729 - <Flex gap="3"> 730 - <TextField 731 - label="Card Number" 732 - placeholder="1234 5678 9012 3456" 733 - style={styles.grow} 734 - /> 735 - <TextField label="CVV" placeholder="123" style={styles.grow} /> 736 - </Flex> 737 - <SmallBody variant="secondary"> 738 - Enter your 16 digit number. 739 - </SmallBody> 740 - </Flex> 741 - <Flex gap="3"> 742 - <Select label="Month" placeholder="MM" style={styles.grow}> 743 - <SelectItem>01</SelectItem> 744 - <SelectItem>02</SelectItem> 745 - <SelectItem>03</SelectItem> 746 - <SelectItem>04</SelectItem> 747 - <SelectItem>05</SelectItem> 748 - <SelectItem>06</SelectItem> 749 - <SelectItem>07</SelectItem> 750 - <SelectItem>08</SelectItem> 751 - <SelectItem>09</SelectItem> 752 - <SelectItem>10</SelectItem> 753 - <SelectItem>11</SelectItem> 754 - <SelectItem>12</SelectItem> 755 - </Select> 756 - <Select label="Year" placeholder="YYYY" style={styles.grow}> 757 - <SelectItem>2025</SelectItem> 758 - <SelectItem>2026</SelectItem> 759 - <SelectItem>2027</SelectItem> 760 - <SelectItem>2028</SelectItem> 761 - <SelectItem>2029</SelectItem> 762 - </Select> 763 - </Flex> 764 - <Separator /> 765 - <Flex direction="column" gap="4"> 766 - <Flex direction="column" gap="3"> 767 - <CardTitle>Billing Address</CardTitle> 768 - <CardDescription> 769 - The billing address associated with your payment method 770 - </CardDescription> 771 - </Flex> 772 - <Checkbox>Same as shipping address</Checkbox> 773 - </Flex> 774 - <Separator /> 775 - <TextArea 776 - label="Message" 777 - placeholder="Add any additional comments" 778 - rows={4} 779 - /> 780 - </Flex> 781 - </DialogDescription> 782 - <DialogFooter> 783 - <Button slot="close">Cancel</Button> 784 - <Button>Action</Button> 785 - </DialogFooter> 786 - </Dialog> 787 - </Flex> 788 - ); 789 - } 790 - 791 - function AvatarExample() { 792 - return ( 793 - <Flex direction="column" gap="4"> 794 - {[...buttonSizes, "xl" as const].map((size) => ( 795 - <Avatar 796 - key={size} 797 - size={size} 798 - src="https://github.com/shadcn.png" 799 - fallback="JD" 800 - /> 801 - ))} 802 - </Flex> 803 - ); 804 - } 805 - 806 - const bageVariants = [ 807 - "primary", 808 - "default", 809 - "warning", 810 - "critical", 811 - "success", 812 - ] as const; 813 - 814 - function BadgeExample() { 815 - return ( 816 - <Flex gap="4"> 817 - {bageVariants.map((variant) => ( 818 - <Flex 819 - key={variant} 820 - gap="4" 821 - direction="column" 822 - style={styles.capitalize} 823 - > 824 - <Badge variant={variant}>{variant}</Badge> 825 - <Badge variant={variant} size="md"> 826 - {variant} 827 - </Badge> 828 - <Badge variant={variant}> 829 - <Info /> 830 - {variant} 831 - </Badge> 832 - <Badge variant={variant} size="sm"> 833 - <Info /> 834 - {variant} 835 - </Badge> 836 - </Flex> 837 - ))} 838 - </Flex> 839 - ); 840 - } 841 - 842 - export function KitchenSink() { 843 - return ( 844 - <Flex 845 - direction="column" 846 - gap="10" 847 - style={[gray.bg, gray.text, styles.container]} 848 - > 849 - <TitleCard title="Badges"> 850 - <BadgeExample /> 851 - </TitleCard> 852 - <TitleCard title="Avatars"> 853 - <AvatarExample /> 854 - </TitleCard> 855 - <TitleCard title="Dialog"> 856 - <DialogExample /> 857 - </TitleCard> 858 - <TitleCard title="Alert Dialog"> 859 - <AlertDialogExample /> 860 - </TitleCard> 861 - <CommandMenuExample /> 862 - <TitleCard title="Tree"> 863 - <TreeExample /> 864 - </TitleCard> 865 - <SignUpForm /> 866 - <PaymentMethod /> 867 - <TitleCard title="Buttons"> 868 - <Buttons /> 869 - </TitleCard> 870 - <TitleCard title="Button Groups"> 871 - <ButtonGroups /> 872 - </TitleCard> 873 - <TitleCard title="Toggle Buttons"> 874 - <Flex direction="column" gap="4"> 875 - {buttons.map((button) => ( 876 - <Flex key={button} gap="8"> 877 - {buttonSizes.map( 878 - (size) => 879 - button !== "critical" && ( 880 - <Flex key={`${button}-${size}`} gap="2"> 881 - <ToggleButton variant={button} size={size}> 882 - <Pin /> 883 - </ToggleButton> 884 - <ToggleButton variant={button} size={size}> 885 - Pin 886 - </ToggleButton> 887 - <ToggleButton variant={button} size={size}> 888 - <Pin /> 889 - Pin 890 - </ToggleButton> 891 - </Flex> 892 - ), 893 - )} 894 - </Flex> 895 - ))} 896 - </Flex> 897 - </TitleCard> 898 - <TitleCard title="Toggle Button Groups"> 899 - <ToggleButtonGroups /> 900 - </TitleCard> 901 - <TitleCard title="Checkboxes"> 902 - <Checkboxes /> 903 - </TitleCard> 904 - <TitleCard title="Checkbox Groups"> 905 - <CheckboxGroups /> 906 - </TitleCard> 907 - <TitleCard title="Radios"> 908 - <Radios /> 909 - </TitleCard> 910 - <TitleCard title="Text Fields"> 911 - <TextFields /> 912 - </TitleCard> 913 - <TitleCard title="Button Groups"> 914 - <ButtonGroups /> 915 - </TitleCard> 916 - <TitleCard title="Menus"> 917 - <MenuExample /> 918 - </TitleCard> 919 - <TitleCard title="Form Elements"> 920 - <FormElements /> 921 - </TitleCard> 922 - <TitleCard title="Tooltips"> 923 - <Tooltip text="Tooltip"> 924 - <Button>Hover me</Button> 925 - </Tooltip> 926 - </TitleCard> 927 - <TitleCard title="Popovers"> 928 - <Popover trigger={<Button>Click me</Button>} placement="top"> 929 - <SmallBody>Content</SmallBody> 930 - </Popover> 931 - </TitleCard> 932 - <TitleCard title="Typography"> 933 - <Typography /> 934 - </TitleCard> 935 - </Flex> 936 - ); 937 - }
-183
apps/example/src/components/alert-dialog/index.tsx
··· 1 - "use client"; 2 - 3 - import type { DialogTriggerProps } from "react-aria-components"; 4 - 5 - import * as stylex from "@stylexjs/stylex"; 6 - import { X } from "lucide-react"; 7 - import { use } from "react"; 8 - import { mergeProps } from "react-aria"; 9 - import { 10 - Dialog as AriaDialog, 11 - DialogTrigger, 12 - Heading, 13 - Modal, 14 - ModalOverlay, 15 - OverlayTriggerStateContext, 16 - } from "react-aria-components"; 17 - 18 - import type { ButtonProps } from "../button"; 19 - 20 - import { Button } from "../button"; 21 - import { IconButton } from "../icon-button"; 22 - import { spacing } from "../theme/spacing.stylex"; 23 - import { typeramp } from "../theme/typography.stylex"; 24 - import { useDialogStyles } from "../theme/useDialogStyles"; 25 - 26 - const styles = stylex.create({ 27 - dialog: { 28 - paddingBottom: spacing["2"], 29 - paddingTop: spacing["2"], 30 - }, 31 - header: { 32 - gap: spacing["2"], 33 - alignItems: "center", 34 - display: "flex", 35 - justifyContent: "space-between", 36 - height: spacing["8"], 37 - paddingLeft: spacing["4"], 38 - paddingRight: spacing["4"], 39 - }, 40 - description: { 41 - paddingBottom: spacing["4"], 42 - paddingLeft: spacing["4"], 43 - paddingRight: spacing["4"], 44 - paddingTop: spacing["4"], 45 - }, 46 - footer: { 47 - gap: spacing["2"], 48 - display: "flex", 49 - justifyContent: "flex-end", 50 - paddingBottom: spacing["2"], 51 - paddingLeft: spacing["4"], 52 - paddingRight: spacing["4"], 53 - }, 54 - }); 55 - 56 - export interface AlertDialogProps extends DialogTriggerProps { 57 - trigger: React.ReactNode; 58 - children: React.ReactNode; 59 - } 60 - 61 - export const AlertDialog = ({ 62 - trigger, 63 - children, 64 - defaultOpen, 65 - isOpen, 66 - onOpenChange, 67 - }: AlertDialogProps) => { 68 - const dialogStyles = useDialogStyles({ size: "sm" }); 69 - 70 - return ( 71 - <DialogTrigger 72 - defaultOpen={defaultOpen} 73 - isOpen={isOpen} 74 - onOpenChange={onOpenChange} 75 - > 76 - {trigger} 77 - 78 - <ModalOverlay 79 - isKeyboardDismissDisabled 80 - {...stylex.props(dialogStyles.overlay)} 81 - > 82 - <Modal {...stylex.props(dialogStyles.modal)}> 83 - <AriaDialog 84 - {...stylex.props(dialogStyles.dialog, styles.dialog)} 85 - role="alertdialog" 86 - > 87 - {children} 88 - </AriaDialog> 89 - </Modal> 90 - </ModalOverlay> 91 - </DialogTrigger> 92 - ); 93 - }; 94 - 95 - export interface AlertDialogHeaderProps extends Omit< 96 - React.ComponentProps<"div">, 97 - "style" | "className" 98 - > { 99 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 100 - } 101 - 102 - export const AlertDialogHeader = ({ 103 - children, 104 - style, 105 - }: AlertDialogHeaderProps) => { 106 - return ( 107 - <div {...stylex.props(styles.header, typeramp.heading5, style)}> 108 - <Heading>{children}</Heading> 109 - <IconButton label="Close" size="sm" variant="tertiary" slot="close"> 110 - <X /> 111 - </IconButton> 112 - </div> 113 - ); 114 - }; 115 - 116 - export interface AlertDialogDescriptionProps extends Omit< 117 - React.ComponentProps<"div">, 118 - "style" | "className" 119 - > { 120 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 121 - } 122 - 123 - export const AlertDialogDescription = ({ 124 - children, 125 - style, 126 - }: AlertDialogDescriptionProps) => { 127 - return ( 128 - <div {...stylex.props(styles.description, typeramp.body, style)}> 129 - {children} 130 - </div> 131 - ); 132 - }; 133 - 134 - export interface AlertDialogFooterProps extends Omit< 135 - React.ComponentProps<"div">, 136 - "style" | "className" 137 - > { 138 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 139 - } 140 - 141 - export const AlertDialogFooter = ({ 142 - children, 143 - style, 144 - }: AlertDialogFooterProps) => { 145 - return <div {...stylex.props(styles.footer, style)}>{children}</div>; 146 - }; 147 - 148 - export type AlertDialogCancelButtonProps = Omit<ButtonProps, "slot">; 149 - 150 - export const AlertDialogCancelButton = ({ 151 - children = "Cancel", 152 - ...props 153 - }: AlertDialogCancelButtonProps) => { 154 - return ( 155 - <Button variant="secondary" {...props} slot="close"> 156 - {children} 157 - </Button> 158 - ); 159 - }; 160 - 161 - export type AlertDialogActionButtonProps = ButtonProps & { 162 - /** 163 - * Whether to close the dialog when the button is pressed. 164 - * If you are doing somthing async, you likely want to set this to false 165 - * and use isLoading=true. 166 - */ 167 - closeOnPress?: boolean; 168 - }; 169 - 170 - export const AlertDialogActionButton = ({ 171 - closeOnPress = true, 172 - children = "Ok", 173 - ...props 174 - }: AlertDialogActionButtonProps) => { 175 - const state = use(OverlayTriggerStateContext); 176 - const onPress = () => { 177 - if (closeOnPress) { 178 - state?.close(); 179 - } 180 - }; 181 - 182 - return <Button {...mergeProps(props, { onPress })}>{children}</Button>; 183 - };
-129
apps/example/src/components/avatar/index.tsx
··· 1 - import * as stylex from "@stylexjs/stylex"; 2 - import { use, useLayoutEffect, useState } from "react"; 3 - 4 - import type { Size } from "../types"; 5 - 6 - import { SizeContext } from "../context"; 7 - import { slate } from "../theme/colors.stylex"; 8 - import { radius } from "../theme/radius.stylex"; 9 - import { spacing } from "../theme/spacing.stylex"; 10 - import { 11 - fontFamily, 12 - fontSize, 13 - fontWeight, 14 - lineHeight, 15 - } from "../theme/typography.stylex"; 16 - 17 - const styles = stylex.create({ 18 - wrapper: { 19 - borderColor: slate.border1, 20 - borderStyle: "solid", 21 - borderWidth: 1, 22 - overflow: "hidden", 23 - alignItems: "center", 24 - backgroundColor: slate.component1, 25 - display: "flex", 26 - justifyContent: "center", 27 - }, 28 - sm: { 29 - borderRadius: radius["sm"], 30 - height: spacing["6"], 31 - width: spacing["6"], 32 - }, 33 - md: { 34 - borderRadius: radius["md"], 35 - height: spacing["8"], 36 - width: spacing["8"], 37 - }, 38 - lg: { 39 - borderRadius: radius["lg"], 40 - height: spacing["10"], 41 - width: spacing["10"], 42 - }, 43 - xl: { 44 - borderRadius: radius["xl"], 45 - height: spacing["14"], 46 - width: spacing["14"], 47 - }, 48 - image: { 49 - objectFit: "cover", 50 - objectPosition: "center", 51 - height: "100%", 52 - width: "100%", 53 - }, 54 - fallback: { 55 - color: slate.text1, 56 - fontFamily: fontFamily["sans"], 57 - fontWeight: fontWeight["medium"], 58 - lineHeight: lineHeight["none"], 59 - }, 60 - smFallback: { 61 - fontSize: fontSize["sm"], 62 - }, 63 - mdFallback: { 64 - fontSize: fontSize["base"], 65 - }, 66 - lgFallback: { 67 - fontSize: fontSize["lg"], 68 - }, 69 - xlFallback: { 70 - fontSize: fontSize["xl"], 71 - }, 72 - }); 73 - 74 - export interface AvatarProps extends Omit< 75 - React.ComponentProps<"div">, 76 - "style" | "className" | "children" 77 - > { 78 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 79 - src: string; 80 - alt?: string; 81 - fallback: React.ReactNode; 82 - size?: Size | "xl"; 83 - } 84 - 85 - export function Avatar({ 86 - style, 87 - alt = "", 88 - src, 89 - fallback, 90 - size: sizeProp, 91 - ...props 92 - }: AvatarProps) { 93 - const size = sizeProp || use(SizeContext); 94 - const [imageLoaded, setImageLoaded] = useState< 95 - "loading" | "loaded" | "error" 96 - >("loading"); 97 - 98 - useLayoutEffect(() => { 99 - if (!src) return; 100 - 101 - const onLoad = () => setImageLoaded("loaded"); 102 - const onError = () => setImageLoaded("error"); 103 - 104 - const image = new Image(); 105 - 106 - image.addEventListener("load", onLoad); 107 - image.addEventListener("error", onError); 108 - 109 - image.src = src; 110 - 111 - return () => { 112 - image.removeEventListener("load", onLoad); 113 - image.removeEventListener("error", onError); 114 - }; 115 - }, [src]); 116 - 117 - return ( 118 - <div {...props} {...stylex.props(styles.wrapper, styles[size], style)}> 119 - {imageLoaded === "loaded" && ( 120 - <img {...stylex.props(styles.image)} src={src} alt={alt} /> 121 - )} 122 - {(!src || imageLoaded === "error") && ( 123 - <div {...stylex.props(styles.fallback, styles[`${size}Fallback`])}> 124 - {fallback} 125 - </div> 126 - )} 127 - </div> 128 - ); 129 - }
-97
apps/example/src/components/badge/index.tsx
··· 1 - import * as stylex from "@stylexjs/stylex"; 2 - import { use } from "react"; 3 - 4 - import type { Size } from "../types"; 5 - 6 - import { SizeContext } from "../context"; 7 - import { radius } from "../theme/radius.stylex"; 8 - import { 9 - critical, 10 - gray, 11 - primary, 12 - success, 13 - warning, 14 - } from "../theme/semantic-color.stylex"; 15 - import { spacing } from "../theme/spacing.stylex"; 16 - import { fontFamily, fontSize, fontWeight } from "../theme/typography.stylex"; 17 - 18 - const styles = stylex.create({ 19 - wrapper: { 20 - borderStyle: "solid", 21 - borderWidth: 1, 22 - gap: spacing["1"], 23 - overflow: "hidden", 24 - alignItems: "center", 25 - display: "flex", 26 - fontFamily: fontFamily["sans"], 27 - fontWeight: fontWeight["semibold"], 28 - justifyContent: "center", 29 - }, 30 - sm: { 31 - borderRadius: radius["sm"], 32 - fontSize: fontSize["xs"], 33 - height: spacing["4"], 34 - paddingLeft: spacing["2"], 35 - paddingRight: spacing["2"], 36 - }, 37 - md: { 38 - borderRadius: radius["md"], 39 - fontSize: fontSize["sm"], 40 - height: spacing["6"], 41 - paddingLeft: spacing["2"], 42 - paddingRight: spacing["2"], 43 - }, 44 - }); 45 - 46 - export interface BadgeProps extends Omit< 47 - React.ComponentProps<"div">, 48 - "style" | "className" 49 - > { 50 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 51 - size?: Extract<Size, "sm" | "md">; 52 - variant?: "primary" | "default" | "warning" | "critical" | "success"; 53 - } 54 - 55 - export function Badge({ 56 - style, 57 - size: sizeProp, 58 - variant = "default", 59 - ...props 60 - }: BadgeProps) { 61 - const sizeContext = use(SizeContext); 62 - const size = 63 - sizeProp || 64 - (sizeContext === "sm" || sizeContext === "md" ? sizeContext : "md"); 65 - 66 - return ( 67 - <div 68 - {...props} 69 - {...stylex.props( 70 - styles.wrapper, 71 - styles[size], 72 - variant === "primary" && [ 73 - primary.bgDim, 74 - primary.borderDim, 75 - primary.text, 76 - ], 77 - variant === "default" && [gray.bgDim, gray.borderDim, gray.text], 78 - variant === "warning" && [ 79 - warning.bgDim, 80 - warning.borderDim, 81 - warning.text, 82 - ], 83 - variant === "critical" && [ 84 - critical.bgDim, 85 - critical.borderDim, 86 - critical.text, 87 - ], 88 - variant === "success" && [ 89 - success.bgDim, 90 - success.borderDim, 91 - success.text, 92 - ], 93 - style, 94 - )} 95 - /> 96 - ); 97 - }
-52
apps/example/src/components/button-group/index.tsx
··· 1 - "use client"; 2 - 3 - import type { GroupProps } from "react-aria-components"; 4 - 5 - import * as stylex from "@stylexjs/stylex"; 6 - import { Group } from "react-aria-components"; 7 - 8 - import { ButtonGroupContext } from "../button/context"; 9 - 10 - const styles = stylex.create({ 11 - group: { 12 - display: "flex", 13 - }, 14 - horizontal: { 15 - alignItems: "center", 16 - flexDirection: "row", 17 - }, 18 - vertical: { 19 - flexDirection: "column", 20 - }, 21 - }); 22 - 23 - export interface ButtonGroupProps extends Omit< 24 - GroupProps, 25 - "className" | "style" 26 - > { 27 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 28 - orientation?: "horizontal" | "vertical"; 29 - } 30 - 31 - export const ButtonGroup = ({ 32 - children, 33 - style, 34 - orientation = "horizontal", 35 - ...props 36 - }: ButtonGroupProps) => { 37 - return ( 38 - <ButtonGroupContext value={orientation}> 39 - <Group 40 - {...stylex.props( 41 - styles.group, 42 - orientation === "horizontal" && styles.horizontal, 43 - orientation === "vertical" && styles.vertical, 44 - style, 45 - )} 46 - {...props} 47 - > 48 - {children} 49 - </Group> 50 - </ButtonGroupContext> 51 - ); 52 - };
-5
apps/example/src/components/button/context.ts
··· 1 - import { createContext } from "react"; 2 - 3 - export const ButtonGroupContext = createContext< 4 - undefined | "vertical" | "horizontal" 5 - >(undefined);
-35
apps/example/src/components/button/index.tsx
··· 1 - "use client"; 2 - 3 - import type { ButtonProps as AriaButtonProps } from "react-aria-components"; 4 - 5 - import * as stylex from "@stylexjs/stylex"; 6 - import { Button as AriaButton } from "react-aria-components"; 7 - 8 - import type { ButtonVariant, Size } from "../types"; 9 - 10 - import { useButtonStyles } from "../theme/useButtonStyles"; 11 - 12 - export interface ButtonProps extends Omit< 13 - AriaButtonProps, 14 - "className" | "style" 15 - > { 16 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 17 - variant?: ButtonVariant; 18 - size?: Size; 19 - } 20 - 21 - export const Button = ({ 22 - children, 23 - style, 24 - variant = "primary", 25 - size, 26 - ...props 27 - }: ButtonProps) => { 28 - const buttonStyles = useButtonStyles({ variant, size }); 29 - 30 - return ( 31 - <AriaButton {...stylex.props(buttonStyles, style)} {...props}> 32 - {children} 33 - </AriaButton> 34 - ); 35 - };
-2
apps/example/src/components/button/types.ts
··· 1 - export type ButtonVariant = "primary" | "secondary" | "tertiary" | "outline"; 2 - export type ButtonSize = "sm" | "md" | "lg";
-178
apps/example/src/components/button/useButtonStyles.ts
··· 1 - "use client"; 2 - 3 - import * as stylex from "@stylexjs/stylex"; 4 - import { use } from "react"; 5 - 6 - import type { ButtonVariant, Size } from "../types"; 7 - 8 - import { animationDuration } from "../theme/animations.stylex"; 9 - import { slate } from "../theme/colors.stylex"; 10 - import { radius } from "../theme/radius.stylex"; 11 - import { gray, primary } from "../theme/semantic-color.stylex"; 12 - import { shadow } from "../theme/shadow.stylex"; 13 - import { spacing } from "../theme/spacing.stylex"; 14 - import { 15 - fontFamily, 16 - fontSize, 17 - fontWeight, 18 - lineHeight, 19 - } from "../theme/typography.stylex"; 20 - import { ButtonGroupContext } from "./context"; 21 - 22 - const styles = stylex.create({ 23 - shadow: { 24 - boxShadow: shadow["xs"], 25 - }, 26 - base: { 27 - borderRadius: radius["md"], 28 - borderStyle: "solid", 29 - borderWidth: 1, 30 - gap: spacing["1"], 31 - alignItems: "center", 32 - boxSizing: "border-box", 33 - display: "inline-flex", 34 - flexShrink: 0, 35 - fontFamily: fontFamily["sans"], 36 - fontWeight: fontWeight["medium"], 37 - justifyContent: "center", 38 - opacity: { 39 - ":disabled": 0.5, 40 - }, 41 - pointerEvents: { 42 - ":disabled": "none", 43 - }, 44 - transitionDuration: animationDuration.fast, 45 - transitionProperty: "all", 46 - transitionTimingFunction: "ease-in-out", 47 - whiteSpace: "nowrap", 48 - 49 - // eslint-disable-next-line @stylexjs/no-legacy-contextual-styles, @stylexjs/valid-styles 50 - ":is(*) svg": { 51 - flexShrink: 0, 52 - pointerEvents: "none", 53 - height: spacing["4"], 54 - width: spacing["4"], 55 - }, 56 - }, 57 - small: { 58 - fontSize: fontSize["xs"], 59 - lineHeight: lineHeight["xs"], 60 - height: spacing["7"], 61 - paddingLeft: { 62 - default: spacing["2"], 63 - }, 64 - paddingRight: spacing["2"], 65 - 66 - // eslint-disable-next-line @stylexjs/no-legacy-contextual-styles, @stylexjs/valid-styles 67 - ":is(*) svg": { 68 - flexShrink: 0, 69 - pointerEvents: "none", 70 - height: spacing["3.5"], 71 - width: spacing["3.5"], 72 - }, 73 - }, 74 - medium: { 75 - gap: spacing["1.5"], 76 - fontSize: fontSize["sm"], 77 - lineHeight: lineHeight["xs"], 78 - height: spacing["8"], 79 - paddingLeft: { 80 - default: spacing["3"], 81 - ":has(svg+*)": spacing["2.5"], 82 - }, 83 - paddingRight: spacing["3"], 84 - }, 85 - large: { 86 - gap: spacing["2"], 87 - height: spacing["10"], 88 - paddingLeft: { 89 - default: spacing["4"], 90 - ":has(svg+*)": spacing["3"], 91 - }, 92 - paddingRight: spacing["4"], 93 - }, 94 - outline: { 95 - borderWidth: 1, 96 - }, 97 - secondary: { 98 - borderColor: { 99 - default: slate.component1, 100 - ":hover": slate.component2, 101 - ":active": slate.component3, 102 - }, 103 - }, 104 - tertiary: { 105 - borderColor: { 106 - default: "transparent", 107 - ":hover": slate.component2, 108 - ":active": slate.component3, 109 - }, 110 - }, 111 - 112 - groupHorizontal: { 113 - borderBottomLeftRadius: { ":not(:first-child)": 0 }, 114 - borderBottomRightRadius: { ":not(:last-child)": 0 }, 115 - borderLeftWidth: { ":not(:first-child)": 0 }, 116 - borderTopLeftRadius: { ":not(:first-child)": 0 }, 117 - borderTopRightRadius: { ":not(:last-child)": 0 }, 118 - }, 119 - secondaryGroupHorizontal: { 120 - borderRightColor: { ":not(:last-child)": slate.border2 }, 121 - }, 122 - groupVertical: { 123 - borderBottomLeftRadius: { ":not(:last-child)": 0 }, 124 - borderBottomRightRadius: { ":not(:last-child)": 0 }, 125 - borderTopLeftRadius: { ":not(:first-child)": 0 }, 126 - borderTopRightRadius: { ":not(:first-child)": 0 }, 127 - borderTopWidth: { ":not(:first-child)": 0 }, 128 - }, 129 - secondaryGroupVertical: { 130 - borderBottomColor: { ":not(:last-child)": slate.border2 }, 131 - }, 132 - }); 133 - 134 - export const useButtonStyles = ({ 135 - variant = "primary", 136 - size = "md", 137 - }: { 138 - variant?: ButtonVariant; 139 - size?: Size; 140 - }) => { 141 - const group = use(ButtonGroupContext); 142 - 143 - return [ 144 - styles.base, 145 - group === "horizontal" && styles.groupHorizontal, 146 - group === "vertical" && styles.groupVertical, 147 - variant === "primary" && [ 148 - primary.bgAction, 149 - primary.borderInteractive, 150 - primary.text, 151 - styles.shadow, 152 - ], 153 - variant === "secondary" && [ 154 - gray.bgUi, 155 - styles.secondary, 156 - gray.text, 157 - group === "horizontal" && styles.secondaryGroupHorizontal, 158 - group === "vertical" && styles.secondaryGroupVertical, 159 - ], 160 - variant === "tertiary" && [ 161 - gray.bgGhost, 162 - styles.tertiary, 163 - gray.text, 164 - group === "horizontal" && styles.secondaryGroupHorizontal, 165 - group === "vertical" && styles.secondaryGroupVertical, 166 - ], 167 - variant === "outline" && [ 168 - gray.borderInteractive, 169 - gray.bgGhost, 170 - gray.text, 171 - styles.outline, 172 - styles.shadow, 173 - ], 174 - size === "sm" && styles.small, 175 - size === "md" && styles.medium, 176 - size === "lg" && styles.large, 177 - ]; 178 - };
-130
apps/example/src/components/card/index.tsx
··· 1 - import * as stylex from "@stylexjs/stylex"; 2 - 3 - import { Flex } from "../flex"; 4 - import { radius } from "../theme/radius.stylex"; 5 - import { gray } from "../theme/semantic-color.stylex"; 6 - import { spacing } from "../theme/spacing.stylex"; 7 - import { fontFamily, fontSize, fontWeight } from "../theme/typography.stylex"; 8 - 9 - const styles = stylex.create({ 10 - card: { 11 - borderRadius: radius["lg"], 12 - gap: spacing["6"], 13 - display: "flex", 14 - flexDirection: "column", 15 - fontFamily: fontFamily["sans"], 16 - width: "fit-content", 17 - }, 18 - cardHeader: { 19 - paddingBottom: { ":last-child": spacing["4"] }, 20 - paddingLeft: spacing["4"], 21 - paddingRight: spacing["4"], 22 - paddingTop: spacing["5"], 23 - }, 24 - cardTitle: { 25 - fontSize: fontSize["lg"], 26 - fontWeight: fontWeight["bold"], 27 - }, 28 - cardDescription: { 29 - margin: 0, 30 - fontSize: fontSize["sm"], 31 - fontWeight: fontWeight["normal"], 32 - }, 33 - cardBody: { 34 - paddingBottom: { ":last-child": spacing["4"] }, 35 - paddingLeft: spacing["4"], 36 - paddingRight: spacing["4"], 37 - }, 38 - cardFooter: { 39 - paddingBottom: spacing["5"], 40 - paddingLeft: spacing["4"], 41 - paddingRight: spacing["4"], 42 - 43 - gap: spacing["2"], 44 - display: "flex", 45 - justifyContent: "flex-end", 46 - }, 47 - }); 48 - 49 - export interface CardProps extends Omit< 50 - React.ComponentProps<"div">, 51 - "style" | "className" 52 - > { 53 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 54 - } 55 - 56 - export const Card = ({ style, ...props }: CardProps) => { 57 - return ( 58 - <div 59 - {...props} 60 - {...stylex.props(styles.card, gray.bgSubtle, gray.border, style)} 61 - /> 62 - ); 63 - }; 64 - 65 - export interface CardHeaderProps extends Omit< 66 - React.ComponentProps<"div">, 67 - "style" | "className" 68 - > { 69 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 70 - } 71 - 72 - export const CardHeader = ({ style, ...props }: CardHeaderProps) => { 73 - return ( 74 - <Flex 75 - {...props} 76 - style={[styles.cardHeader as unknown as stylex.StyleXStyles, style]} 77 - direction="column" 78 - gap="3" 79 - /> 80 - ); 81 - }; 82 - 83 - export interface CardTitleProps extends Omit< 84 - React.ComponentProps<"h2">, 85 - "style" | "className" 86 - > { 87 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 88 - } 89 - 90 - export const CardTitle = ({ style, ...props }: CardTitleProps) => { 91 - return <div {...props} {...stylex.props(styles.cardTitle, style)} />; 92 - }; 93 - 94 - export interface CardDescriptionProps extends Omit< 95 - React.ComponentProps<"p">, 96 - "style" | "className" 97 - > { 98 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 99 - } 100 - 101 - export const CardDescription = ({ style, ...props }: CardDescriptionProps) => { 102 - return ( 103 - <p 104 - {...props} 105 - {...stylex.props(styles.cardDescription, gray.textDim, style)} 106 - /> 107 - ); 108 - }; 109 - 110 - export interface CardBodyProps extends Omit< 111 - React.ComponentProps<"div">, 112 - "style" | "className" 113 - > { 114 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 115 - } 116 - 117 - export const CardBody = ({ style, ...props }: CardBodyProps) => { 118 - return <div {...props} {...stylex.props(styles.cardBody, style)} />; 119 - }; 120 - 121 - export interface CardFooterProps extends Omit< 122 - React.ComponentProps<"div">, 123 - "style" | "className" 124 - > { 125 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 126 - } 127 - 128 - export const CardFooter = ({ style, ...props }: CardFooterProps) => { 129 - return <div {...props} {...stylex.props(styles.cardFooter, style)} />; 130 - };
-129
apps/example/src/components/checkbox/index.tsx
··· 1 - import type { 2 - CheckboxGroupProps as AriaCheckboxGroupProps, 3 - CheckboxProps as AriaCheckboxProps, 4 - ValidationResult, 5 - } from "react-aria-components"; 6 - 7 - import * as stylex from "@stylexjs/stylex"; 8 - import { Check, Minus } from "lucide-react"; 9 - import { 10 - Checkbox as AriaCheckbox, 11 - CheckboxGroup as AriaCheckboxGroup, 12 - FieldError, 13 - } from "react-aria-components"; 14 - 15 - import type { Size } from "../types"; 16 - 17 - import { Flex } from "../flex"; 18 - import { Description, Label } from "../label"; 19 - import { radius } from "../theme/radius.stylex"; 20 - import { gray, primary } from "../theme/semantic-color.stylex"; 21 - import { spacing } from "../theme/spacing.stylex"; 22 - import { fontFamily, fontSize, lineHeight } from "../theme/typography.stylex"; 23 - 24 - const styles = stylex.create({ 25 - wrapper: { 26 - gap: spacing["2.5"], 27 - alignItems: { 28 - default: "center", 29 - ":has(p)": "flex-start", 30 - }, 31 - display: "flex", 32 - 33 - fontFamily: fontFamily["sans"], 34 - fontSize: fontSize["sm"], 35 - lineHeight: lineHeight["sm"], 36 - opacity: { ":is([data-disabled])": 0.5 }, 37 - }, 38 - checkbox: { 39 - alignItems: "center", 40 - display: "flex", 41 - justifyContent: "center", 42 - 43 - borderRadius: radius["sm"], 44 - borderWidth: 2, 45 - height: spacing["4"], 46 - width: spacing["4"], 47 - }, 48 - checked: { 49 - color: "white", 50 - }, 51 - group: { 52 - gap: spacing["3"], 53 - display: "flex", 54 - flexDirection: "column", 55 - }, 56 - }); 57 - 58 - interface CheckboxGroupProps extends Omit< 59 - AriaCheckboxGroupProps, 60 - "children" | "style" | "className" 61 - > { 62 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 63 - children?: React.ReactNode; 64 - label?: React.ReactNode; 65 - description?: string; 66 - errorMessage?: string | ((validation: ValidationResult) => string); 67 - size?: Size; 68 - } 69 - 70 - export function CheckboxGroup({ 71 - label, 72 - description, 73 - errorMessage, 74 - children, 75 - size, 76 - style, 77 - ...props 78 - }: CheckboxGroupProps) { 79 - return ( 80 - <AriaCheckboxGroup {...props} {...stylex.props(styles.group, style)}> 81 - {label !== null && <Label size={size}>{label}</Label>} 82 - <Flex direction="column" gap="2"> 83 - {children} 84 - </Flex> 85 - {description && <Description size={size}>{description}</Description>} 86 - <FieldError>{errorMessage}</FieldError> 87 - </AriaCheckboxGroup> 88 - ); 89 - } 90 - 91 - export interface CheckboxProps extends Omit< 92 - AriaCheckboxProps, 93 - "className" | "style" | "children" 94 - > { 95 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 96 - children?: React.ReactNode; 97 - } 98 - 99 - export function Checkbox({ children, style, ...props }: CheckboxProps) { 100 - return ( 101 - <AriaCheckbox {...props} {...stylex.props(styles.wrapper, style)}> 102 - {({ isIndeterminate, isSelected, isDisabled }) => ( 103 - <> 104 - <div 105 - {...stylex.props( 106 - styles.checkbox, 107 - isDisabled 108 - ? [gray.bgSolid, gray.border, styles.checked] 109 - : isSelected 110 - ? [primary.bgSolid, primary.borderInteractive, styles.checked] 111 - : [gray.borderInteractive], 112 - )} 113 - > 114 - {isIndeterminate ? ( 115 - <Minus size={16} /> 116 - ) : isSelected ? ( 117 - <Check size={16} /> 118 - ) : null} 119 - </div> 120 - {children !== null && ( 121 - <Flex direction="column" gap="1"> 122 - {children} 123 - </Flex> 124 - )} 125 - </> 126 - )} 127 - </AriaCheckbox> 128 - ); 129 - }
-77
apps/example/src/components/color-field/index.tsx
··· 1 - import type { 2 - ColorFieldProps as AriaColorFieldProps, 3 - InputProps, 4 - ValidationResult, 5 - } from "react-aria-components"; 6 - 7 - import * as stylex from "@stylexjs/stylex"; 8 - import { useRef } from "react"; 9 - import { 10 - ColorField as AriaColorField, 11 - FieldError, 12 - Input, 13 - } from "react-aria-components"; 14 - 15 - import type { Size } from "../types"; 16 - 17 - import { Description, Label } from "../label"; 18 - import { useInputStyles } from "../theme/useInputStyles"; 19 - 20 - export interface ColorFieldProps 21 - extends 22 - Omit<AriaColorFieldProps, "style" | "className">, 23 - Pick<InputProps, "placeholder"> { 24 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 25 - label?: React.ReactNode; 26 - description?: string; 27 - errorMessage?: string | ((validation: ValidationResult) => string); 28 - size?: Size; 29 - prefix?: React.ReactNode; 30 - suffix?: React.ReactNode; 31 - } 32 - 33 - export function ColorField({ 34 - label, 35 - description, 36 - errorMessage, 37 - style, 38 - size, 39 - prefix, 40 - suffix, 41 - placeholder, 42 - ...props 43 - }: ColorFieldProps) { 44 - const inputRef = useRef<HTMLInputElement>(null); 45 - const inputStyles = useInputStyles({ size }); 46 - 47 - return ( 48 - <AriaColorField {...props} {...stylex.props(inputStyles.field, style)}> 49 - {label !== null && <Label size={size}>{label}</Label>} 50 - {/* 51 - This onClick is specifically for mouse users not clicking directly on the input. 52 - A keyboard user would not encounter the same issue. 53 - */} 54 - {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 55 - <div 56 - {...stylex.props(inputStyles.wrapper)} 57 - onClick={() => inputRef.current?.focus()} 58 - > 59 - {prefix !== null && ( 60 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 61 - )} 62 - <Input 63 - placeholder={placeholder} 64 - ref={inputRef} 65 - {...stylex.props(inputStyles.input)} 66 - /> 67 - {suffix !== null && ( 68 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 69 - )} 70 - </div> 71 - {description !== undefined && ( 72 - <Description size={size}>{description}</Description> 73 - )} 74 - <FieldError>{errorMessage}</FieldError> 75 - </AriaColorField> 76 - ); 77 - }
-149
apps/example/src/components/combobox/index.tsx
··· 1 - import type { 2 - ComboBoxProps as AriaComboBoxProps, 3 - ListBoxProps, 4 - PopoverProps, 5 - ValidationResult, 6 - } from "react-aria-components"; 7 - 8 - import * as stylex from "@stylexjs/stylex"; 9 - import { ChevronDown } from "lucide-react"; 10 - import { use } from "react"; 11 - import { 12 - ComboBox as AriaComboBox, 13 - Button, 14 - FieldError, 15 - Input, 16 - Popover, 17 - } from "react-aria-components"; 18 - 19 - import type { Size } from "../types"; 20 - 21 - import { SizeContext } from "../context"; 22 - import { IconButton } from "../icon-button"; 23 - import { Description, Label } from "../label"; 24 - import { ListBox } from "../listbox"; 25 - import { spacing } from "../theme/spacing.stylex"; 26 - import { useInputStyles } from "../theme/useInputStyles"; 27 - import { usePopoverStyles } from "../theme/usePopoverStyles"; 28 - import { SmallBody } from "../typography"; 29 - 30 - const styles = stylex.create({ 31 - matchWidth: { 32 - width: "var(--trigger-width)", 33 - }, 34 - emptyState: { 35 - padding: spacing["4"], 36 - display: "flex", 37 - justifyContent: "center", 38 - }, 39 - }); 40 - 41 - function EmptyState() { 42 - return ( 43 - <div {...stylex.props(styles.emptyState)}> 44 - <SmallBody variant="secondary">No items found</SmallBody> 45 - </div> 46 - ); 47 - } 48 - 49 - export interface ComboBoxProps<T extends object> 50 - extends 51 - Omit<AriaComboBoxProps<T>, "children" | "style" | "className">, 52 - Pick< 53 - PopoverProps, 54 - | "shouldCloseOnInteractOutside" 55 - | "shouldFlip" 56 - | "shouldUpdatePosition" 57 - | "placement" 58 - >, 59 - Pick<ListBoxProps<T>, "renderEmptyState"> { 60 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 61 - label?: string; 62 - description?: string; 63 - errorMessage?: string | ((validation: ValidationResult) => string); 64 - items?: Iterable<T>; 65 - children: React.ReactNode | ((item: T) => React.ReactNode); 66 - size?: Size; 67 - placeholder?: string; 68 - prefix?: React.ReactNode; 69 - suffix?: React.ReactNode; 70 - } 71 - 72 - export function ComboBox<T extends object>({ 73 - label, 74 - description, 75 - errorMessage, 76 - children, 77 - items, 78 - style, 79 - size: sizeProp, 80 - shouldCloseOnInteractOutside, 81 - shouldFlip, 82 - shouldUpdatePosition, 83 - placement, 84 - placeholder = "Select an option", 85 - prefix, 86 - suffix, 87 - renderEmptyState, 88 - ...props 89 - }: ComboBoxProps<T>) { 90 - const size = sizeProp || use(SizeContext); 91 - const inputStyles = useInputStyles({ size }); 92 - const popoverStyles = usePopoverStyles(); 93 - 94 - return ( 95 - <SizeContext value={size}> 96 - <AriaComboBox {...props} {...stylex.props(inputStyles.field, style)}> 97 - {label && <Label size={size}>{label}</Label>} 98 - <Button {...stylex.props(inputStyles.wrapper)}> 99 - {prefix !== null && ( 100 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 101 - )} 102 - <Input 103 - {...stylex.props(inputStyles.input)} 104 - placeholder={placeholder} 105 - /> 106 - {suffix !== null && ( 107 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 108 - )} 109 - <div {...stylex.props(inputStyles.addon)}> 110 - <IconButton size="sm" variant="secondary" label="Open combobox"> 111 - <ChevronDown size={16} aria-hidden="true" /> 112 - </IconButton> 113 - </div> 114 - </Button> 115 - {description && <Description size={size}>{description}</Description>} 116 - <FieldError>{errorMessage}</FieldError> 117 - <Popover 118 - containerPadding={8} 119 - shouldCloseOnInteractOutside={shouldCloseOnInteractOutside} 120 - shouldFlip={shouldFlip} 121 - shouldUpdatePosition={shouldUpdatePosition} 122 - placement={placement} 123 - > 124 - <ListBox 125 - items={items} 126 - {...stylex.props(popoverStyles, styles.matchWidth)} 127 - renderEmptyState={renderEmptyState || EmptyState} 128 - > 129 - {children} 130 - </ListBox> 131 - </Popover> 132 - </AriaComboBox> 133 - </SizeContext> 134 - ); 135 - } 136 - 137 - export type { 138 - ListBoxItemProps as ComboBoxItemProps, 139 - ListBoxSectionProps as ComboBoxSectionProps, 140 - ListBoxSectionHeaderProps as ComboBoxSectionHeaderProps, 141 - ListBoxSeparatorProps as ComboBoxSeparatorProps, 142 - } from "../listbox"; 143 - 144 - export { 145 - ListBoxItem as ComboBoxItem, 146 - ListBoxSection as ComboBoxSection, 147 - ListBoxSectionHeader as ComboBoxSectionHeader, 148 - ListBoxSeparator as ComboBoxSeparator, 149 - } from "../listbox";
-142
apps/example/src/components/command-menu/index.tsx
··· 1 - import type { 2 - AutocompleteProps as AriaAutocompleteProps, 3 - InputProps, 4 - } from "react-aria-components"; 5 - import type { OverlayTriggerProps } from "react-stately"; 6 - 7 - import { useControlledState } from "@react-stately/utils"; 8 - import * as stylex from "@stylexjs/stylex"; 9 - import { useEffect, useEffectEvent } from "react"; 10 - import { 11 - Autocomplete, 12 - Dialog, 13 - Menu, 14 - Modal, 15 - ModalOverlay, 16 - useFilter, 17 - } from "react-aria-components"; 18 - 19 - import { SizeContext } from "../context"; 20 - import { SearchField } from "../search-field"; 21 - import { Separator } from "../separator"; 22 - import { spacing } from "../theme/spacing.stylex"; 23 - import { useDialogStyles } from "../theme/useDialogStyles"; 24 - 25 - const styles = stylex.create({ 26 - menu: { 27 - flexGrow: 1, 28 - marginLeft: `calc(${spacing["0.5"]} * -1)`, 29 - marginRight: `calc(${spacing["0.5"]} * -1)`, 30 - minHeight: 0, 31 - overflowY: "auto", 32 - paddingBottom: spacing["2"], 33 - paddingLeft: spacing["3"], 34 - paddingRight: spacing["3"], 35 - paddingTop: spacing["2"], 36 - }, 37 - searchField: { 38 - paddingBottom: spacing["3"], 39 - paddingLeft: spacing["3"], 40 - paddingRight: spacing["3"], 41 - paddingTop: spacing["3"], 42 - }, 43 - }); 44 - 45 - export interface CommandMenuProps<T extends object> 46 - extends 47 - OverlayTriggerProps, 48 - Pick<InputProps, "placeholder">, 49 - AriaAutocompleteProps<T> { 50 - children: React.ReactNode; 51 - disableGlobalShortcut?: boolean; 52 - } 53 - 54 - export function CommandMenu<T extends object>({ 55 - defaultOpen, 56 - isOpen: isOpenProp, 57 - onOpenChange, 58 - filter, 59 - placeholder = "Search commands", 60 - children, 61 - defaultInputValue, 62 - disableAutoFocusFirst, 63 - disableVirtualFocus, 64 - inputValue, 65 - onInputChange, 66 - disableGlobalShortcut = false, 67 - }: CommandMenuProps<T>) { 68 - const defaultFilter = useFilter({ sensitivity: "base" }); 69 - const dialogStyles = useDialogStyles({ size: "sm" }); 70 - const [isOpen, setIsOpen] = useControlledState( 71 - isOpenProp, 72 - defaultOpen ?? false, 73 - onOpenChange, 74 - ); 75 - const onClose = useEffectEvent(() => { 76 - setIsOpen(false); 77 - }); 78 - 79 - useEffect(() => { 80 - if (disableGlobalShortcut) return; 81 - 82 - function handleKeyDown(event: KeyboardEvent) { 83 - if (event.metaKey && event.key === "k") { 84 - setIsOpen(true); 85 - } 86 - } 87 - 88 - globalThis.addEventListener("keydown", handleKeyDown); 89 - 90 - return () => { 91 - globalThis.removeEventListener("keydown", handleKeyDown); 92 - }; 93 - }, [setIsOpen, disableGlobalShortcut]); 94 - 95 - return ( 96 - <SizeContext value="lg"> 97 - <ModalOverlay 98 - isDismissable 99 - isOpen={isOpen} 100 - onOpenChange={setIsOpen} 101 - {...stylex.props(dialogStyles.overlay)} 102 - > 103 - <Modal {...stylex.props(dialogStyles.modal)}> 104 - <Dialog {...stylex.props(dialogStyles.dialog)}> 105 - <Autocomplete 106 - filter={filter ?? defaultFilter.contains} 107 - defaultInputValue={defaultInputValue} 108 - disableAutoFocusFirst={disableAutoFocusFirst} 109 - disableVirtualFocus={disableVirtualFocus} 110 - inputValue={inputValue} 111 - onInputChange={onInputChange} 112 - > 113 - <div {...stylex.props(styles.searchField)}> 114 - {/* This is part of the interaction for a CMD+K menu. */} 115 - {/* eslint-disable-next-line jsx-a11y/no-autofocus */} 116 - <SearchField placeholder={placeholder} autoFocus /> 117 - </div> 118 - <Separator /> 119 - <Menu {...stylex.props(styles.menu)} onAction={onClose}> 120 - {children} 121 - </Menu> 122 - </Autocomplete> 123 - </Dialog> 124 - </Modal> 125 - </ModalOverlay> 126 - </SizeContext> 127 - ); 128 - } 129 - 130 - export type { 131 - MenuItemProps as CommandMenuItemProps, 132 - MenuSectionHeaderProps as CommandMenuSectionHeaderProps, 133 - MenuSectionProps as CommandMenuSectionProps, 134 - MenuSeparatorProps as CommandMenuSeparatorProps, 135 - } from "../menu"; 136 - 137 - export { 138 - MenuItem as CommandMenuItem, 139 - MenuSectionHeader as CommandMenuSectionHeader, 140 - MenuSection as CommandMenuSection, 141 - MenuSeparator as CommandMenuSeparator, 142 - } from "../menu";
-187
apps/example/src/components/context-menu/index.tsx
··· 1 - import type { OverlayTriggerProps } from "@react-types/overlays"; 2 - import type { AriaButtonProps } from "react-aria"; 3 - import type { 4 - MenuProps as AriaMenuProps, 5 - PopoverProps, 6 - } from "react-aria-components"; 7 - 8 - import * as stylex from "@stylexjs/stylex"; 9 - import { 10 - Children, 11 - cloneElement, 12 - createContext, 13 - use, 14 - useCallback, 15 - useRef, 16 - useState, 17 - } from "react"; 18 - import { useMenuTrigger } from "react-aria"; 19 - import { 20 - Menu as AriaMenu, 21 - MenuContext, 22 - OverlayTriggerStateContext, 23 - Popover, 24 - PopoverContext, 25 - Provider, 26 - RootMenuTriggerStateContext, 27 - } from "react-aria-components"; 28 - import { useMenuTriggerState } from "react-stately"; 29 - 30 - import type { Size } from "../types"; 31 - 32 - import { SizeContext } from "../context"; 33 - import { usePopoverStyles } from "../theme/usePopoverStyles"; 34 - 35 - const ContextMenuTriggerPropsContext = createContext< 36 - AriaButtonProps & { ref?: React.Ref<HTMLDivElement> } 37 - >({}); 38 - 39 - interface Position { 40 - x: number; 41 - y: number; 42 - } 43 - 44 - const ContextMenuStateContext = createContext<{ 45 - position: Position; 46 - setPosition: (position: Position) => void; 47 - }>({ 48 - position: { x: 0, y: 0 }, 49 - setPosition: () => {}, 50 - }); 51 - 52 - function ContextMenuRoot({ 53 - children, 54 - ...props 55 - }: OverlayTriggerProps & { children: React.ReactNode }) { 56 - const scrollRef = useRef(null); 57 - const state = useMenuTriggerState(props); 58 - const ref = useRef<HTMLDivElement>(null); 59 - const [position, setPosition] = useState<Position>({ x: 0, y: 0 }); 60 - const { menuTriggerProps, menuProps } = useMenuTrigger( 61 - { ...props, type: "menu" }, 62 - state, 63 - ref, 64 - ); 65 - 66 - return ( 67 - <Provider 68 - values={[ 69 - [MenuContext, { ...menuProps, ref: scrollRef }], 70 - [OverlayTriggerStateContext, state], 71 - [RootMenuTriggerStateContext, state], 72 - [ContextMenuTriggerPropsContext, { ...menuTriggerProps, ref }], 73 - [ContextMenuStateContext, { position, setPosition }], 74 - [ 75 - PopoverContext, 76 - { 77 - trigger: "MenuTrigger", 78 - triggerRef: ref, 79 - scrollRef, 80 - placement: "bottom start", 81 - "aria-labelledby": menuProps["aria-labelledby"], 82 - }, 83 - ], 84 - ]} 85 - > 86 - {children} 87 - </Provider> 88 - ); 89 - } 90 - 91 - function ContextMenuTrigger({ 92 - children, 93 - ...props 94 - }: OverlayTriggerProps & { children: React.ReactNode }) { 95 - const overlayTriggerState = use(OverlayTriggerStateContext); 96 - const menuTriggerProps = use(ContextMenuTriggerPropsContext); 97 - const { position, setPosition } = use(ContextMenuStateContext); 98 - const onContextMenu = useCallback( 99 - (e: React.MouseEvent<HTMLButtonElement>) => { 100 - e.preventDefault(); 101 - e.stopPropagation(); 102 - overlayTriggerState?.open(); 103 - setPosition({ x: e.pageX, y: e.pageY }); 104 - }, 105 - [overlayTriggerState, setPosition], 106 - ); 107 - 108 - // eslint-disable-next-line @eslint-react/no-children-count 109 - if (Children.count(children) !== 1) { 110 - throw new Error("ContextMenuTrigger must have exactly one child"); 111 - } 112 - 113 - return ( 114 - <> 115 - {/* eslint-disable-next-line @eslint-react/no-clone-element */} 116 - {cloneElement( 117 - children as React.ReactElement<React.HTMLAttributes<HTMLElement>>, 118 - { 119 - ...props, 120 - "aria-controls": menuTriggerProps["aria-controls"], 121 - "aria-expanded": menuTriggerProps["aria-expanded"], 122 - "aria-haspopup": menuTriggerProps["aria-haspopup"], 123 - id: menuTriggerProps["id"], 124 - onContextMenu: onContextMenu, 125 - }, 126 - )} 127 - <div 128 - ref={menuTriggerProps.ref} 129 - style={{ position: "absolute", top: position.y, left: position.x }} 130 - /> 131 - </> 132 - ); 133 - } 134 - 135 - export interface ContextMenuProps<T extends object> 136 - extends 137 - OverlayTriggerProps, 138 - Omit<AriaMenuProps<T>, "children" | "className" | "style">, 139 - Pick< 140 - PopoverProps, 141 - | "shouldCloseOnInteractOutside" 142 - | "shouldFlip" 143 - | "shouldUpdatePosition" 144 - | "placement" 145 - > { 146 - trigger: React.ReactNode; 147 - items?: Iterable<T>; 148 - children: React.ReactNode | ((item: T) => React.ReactNode); 149 - size?: Size; 150 - } 151 - 152 - export function ContextMenu<T extends object>({ 153 - trigger, 154 - size: sizeProp, 155 - defaultOpen, 156 - isOpen, 157 - onOpenChange, 158 - shouldCloseOnInteractOutside, 159 - shouldFlip, 160 - shouldUpdatePosition, 161 - placement, 162 - ...props 163 - }: ContextMenuProps<T>) { 164 - const popoverStyles = usePopoverStyles(); 165 - const size = sizeProp || use(SizeContext); 166 - 167 - return ( 168 - <SizeContext value={size}> 169 - <ContextMenuRoot 170 - defaultOpen={defaultOpen} 171 - isOpen={isOpen} 172 - onOpenChange={onOpenChange} 173 - > 174 - <ContextMenuTrigger>{trigger}</ContextMenuTrigger> 175 - <Popover 176 - containerPadding={8} 177 - shouldCloseOnInteractOutside={shouldCloseOnInteractOutside} 178 - shouldFlip={shouldFlip} 179 - shouldUpdatePosition={shouldUpdatePosition} 180 - placement={placement} 181 - > 182 - <AriaMenu {...props} {...stylex.props(popoverStyles)} /> 183 - </Popover> 184 - </ContextMenuRoot> 185 - </SizeContext> 186 - ); 187 - }
-5
apps/example/src/components/context.ts
··· 1 - import { createContext } from "react"; 2 - 3 - import type { Size } from "./types"; 4 - 5 - export const SizeContext = createContext<Size>("md");
-73
apps/example/src/components/date-field/index.tsx
··· 1 - import type { 2 - DateFieldProps as AriaDateFieldProps, 3 - DateValue, 4 - ValidationResult, 5 - } from "react-aria-components"; 6 - 7 - import * as stylex from "@stylexjs/stylex"; 8 - import { useRef } from "react"; 9 - import { 10 - DateField as AriaDateField, 11 - DateInput, 12 - DateSegment, 13 - FieldError, 14 - } from "react-aria-components"; 15 - 16 - import type { Size } from "../types"; 17 - 18 - import { Description, Label } from "../label"; 19 - import { useInputStyles } from "../theme/useInputStyles"; 20 - 21 - export interface DateFieldProps<T extends DateValue> extends Omit< 22 - AriaDateFieldProps<T>, 23 - "style" | "className" 24 - > { 25 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 26 - label?: React.ReactNode; 27 - description?: string; 28 - errorMessage?: string | ((validation: ValidationResult) => string); 29 - size?: Size; 30 - prefix?: React.ReactNode; 31 - suffix?: React.ReactNode; 32 - } 33 - 34 - export function DateField<T extends DateValue>({ 35 - label, 36 - description, 37 - errorMessage, 38 - style, 39 - size, 40 - prefix, 41 - suffix, 42 - ...props 43 - }: DateFieldProps<T>) { 44 - const inputRef = useRef<HTMLInputElement>(null); 45 - const inputStyles = useInputStyles({ size }); 46 - 47 - return ( 48 - <AriaDateField {...props} {...stylex.props(inputStyles.field, style)}> 49 - {label !== null && <Label size={size}>{label}</Label>} 50 - {/* 51 - This onClick is specifically for mouse users not clicking directly on the input. 52 - A keyboard user would not encounter the same issue. 53 - */} 54 - {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 55 - <div 56 - {...stylex.props(inputStyles.wrapper)} 57 - onClick={() => inputRef.current?.focus()} 58 - > 59 - {prefix !== null && ( 60 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 61 - )} 62 - <DateInput {...stylex.props(inputStyles.input)} ref={inputRef}> 63 - {(segment) => <DateSegment segment={segment} />} 64 - </DateInput> 65 - {suffix !== null && ( 66 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 67 - )} 68 - </div> 69 - {description && <Description size={size}>{description}</Description>} 70 - <FieldError>{errorMessage}</FieldError> 71 - </AriaDateField> 72 - ); 73 - }
-146
apps/example/src/components/dialog/index.tsx
··· 1 - "use client"; 2 - 3 - import type { DialogTriggerProps } from "react-aria-components"; 4 - 5 - import * as stylex from "@stylexjs/stylex"; 6 - import { X } from "lucide-react"; 7 - import { 8 - Dialog as AriaDialog, 9 - DialogTrigger, 10 - Heading, 11 - Modal, 12 - ModalOverlay, 13 - } from "react-aria-components"; 14 - 15 - import type { Size } from "../types"; 16 - 17 - import { IconButton } from "../icon-button"; 18 - import { slate } from "../theme/colors.stylex"; 19 - import { spacing } from "../theme/spacing.stylex"; 20 - import { typeramp } from "../theme/typography.stylex"; 21 - import { useDialogStyles } from "../theme/useDialogStyles"; 22 - 23 - const styles = stylex.create({ 24 - dialog: { 25 - paddingBottom: spacing["2"], 26 - paddingTop: spacing["2"], 27 - }, 28 - header: { 29 - gap: spacing["2"], 30 - alignItems: "center", 31 - display: "flex", 32 - justifyContent: "space-between", 33 - height: spacing["8"], 34 - paddingBottom: spacing["2"], 35 - paddingLeft: spacing["4"], 36 - paddingRight: spacing["4"], 37 - 38 - borderBottomColor: slate.border1, 39 - borderBottomStyle: "solid", 40 - borderBottomWidth: 1, 41 - }, 42 - description: { 43 - paddingBottom: spacing["4"], 44 - paddingLeft: spacing["4"], 45 - paddingRight: spacing["4"], 46 - paddingTop: spacing["4"], 47 - }, 48 - footer: { 49 - gap: spacing["2"], 50 - display: "flex", 51 - justifyContent: "flex-end", 52 - paddingBottom: spacing["2"], 53 - paddingLeft: spacing["4"], 54 - paddingRight: spacing["4"], 55 - paddingTop: spacing["4"], 56 - 57 - borderTopColor: slate.border1, 58 - borderTopStyle: "solid", 59 - borderTopWidth: 1, 60 - }, 61 - }); 62 - 63 - export interface DialogProps extends DialogTriggerProps { 64 - trigger: React.ReactNode; 65 - children: React.ReactNode; 66 - size?: Size; 67 - } 68 - 69 - export const Dialog = ({ 70 - trigger, 71 - children, 72 - defaultOpen, 73 - isOpen, 74 - onOpenChange, 75 - size, 76 - }: DialogProps) => { 77 - const dialogStyles = useDialogStyles({ size }); 78 - 79 - return ( 80 - <DialogTrigger 81 - defaultOpen={defaultOpen} 82 - isOpen={isOpen} 83 - onOpenChange={onOpenChange} 84 - > 85 - {trigger} 86 - 87 - <ModalOverlay 88 - isKeyboardDismissDisabled 89 - {...stylex.props(dialogStyles.overlay)} 90 - > 91 - <Modal {...stylex.props(dialogStyles.modal)}> 92 - <AriaDialog {...stylex.props(dialogStyles.dialog, styles.dialog)}> 93 - {children} 94 - </AriaDialog> 95 - </Modal> 96 - </ModalOverlay> 97 - </DialogTrigger> 98 - ); 99 - }; 100 - 101 - export interface DialogHeaderProps extends Omit< 102 - React.ComponentProps<"div">, 103 - "style" | "className" 104 - > { 105 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 106 - } 107 - 108 - export const DialogHeader = ({ children, style }: DialogHeaderProps) => { 109 - return ( 110 - <div {...stylex.props(styles.header, typeramp.heading5, style)}> 111 - <Heading>{children}</Heading> 112 - <IconButton label="Close" size="sm" variant="tertiary" slot="close"> 113 - <X /> 114 - </IconButton> 115 - </div> 116 - ); 117 - }; 118 - 119 - export interface DialogDescriptionProps extends Omit< 120 - React.ComponentProps<"div">, 121 - "style" | "className" 122 - > { 123 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 124 - } 125 - 126 - export const DialogDescription = ({ 127 - children, 128 - style, 129 - }: DialogDescriptionProps) => { 130 - return ( 131 - <div {...stylex.props(styles.description, typeramp.body, style)}> 132 - {children} 133 - </div> 134 - ); 135 - }; 136 - 137 - export interface DialogFooterProps extends Omit< 138 - React.ComponentProps<"div">, 139 - "style" | "className" 140 - > { 141 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 142 - } 143 - 144 - export const DialogFooter = ({ children, style }: DialogFooterProps) => { 145 - return <div {...stylex.props(styles.footer, style)}>{children}</div>; 146 - };
-153
apps/example/src/components/flex copy/index.tsx
··· 1 - import * as stylex from "@stylexjs/stylex"; 2 - 3 - import type { Spacing } from "../theme/spacing.stylex"; 4 - 5 - import { spacing } from "../theme/spacing.stylex"; 6 - 7 - const styles = stylex.create({ 8 - base: { display: "flex" }, 9 - inline: { display: "inline-flex" }, 10 - row: { flexDirection: "row" }, 11 - "row-reverse": { flexDirection: "row-reverse" }, 12 - column: { flexDirection: "column" }, 13 - "column-reverse": { flexDirection: "column-reverse" }, 14 - wrap: { flexWrap: "wrap" }, 15 - "wrap-reverse": { flexWrap: "wrap-reverse" }, 16 - "justify-start": { justifyContent: "flex-start" }, 17 - "justify-end": { justifyContent: "flex-end" }, 18 - "justify-center": { justifyContent: "center" }, 19 - "justify-between": { justifyContent: "space-between" }, 20 - "justify-around": { justifyContent: "space-around" }, 21 - "justify-evenly": { justifyContent: "space-evenly" }, 22 - "align-stretch": { alignItems: "stretch" }, 23 - "align-start": { alignItems: "flex-start" }, 24 - "align-end": { alignItems: "flex-end" }, 25 - "align-center": { alignItems: "center" }, 26 - "align-baseline": { alignItems: "baseline" }, 27 - "gap-0.5": { gap: spacing["0.5"] }, 28 - "gap-1": { gap: spacing["1"] }, 29 - "gap-1.5": { gap: spacing["1.5"] }, 30 - "gap-2": { gap: spacing["2"] }, 31 - "gap-2.5": { gap: spacing["2.5"] }, 32 - "gap-3": { gap: spacing["3"] }, 33 - "gap-3.5": { gap: spacing["3.5"] }, 34 - "gap-4": { gap: spacing["4"] }, 35 - "gap-5": { gap: spacing["5"] }, 36 - "gap-6": { gap: spacing["6"] }, 37 - "gap-7": { gap: spacing["7"] }, 38 - "gap-8": { gap: spacing["8"] }, 39 - "gap-9": { gap: spacing["9"] }, 40 - "gap-10": { gap: spacing["10"] }, 41 - "gap-11": { gap: spacing["11"] }, 42 - "gap-12": { gap: spacing["12"] }, 43 - "gap-14": { gap: spacing["14"] }, 44 - "gap-16": { gap: spacing["16"] }, 45 - "gap-20": { gap: spacing["20"] }, 46 - "gap-24": { gap: spacing["24"] }, 47 - "gap-28": { gap: spacing["28"] }, 48 - "gap-32": { gap: spacing["32"] }, 49 - "gap-36": { gap: spacing["36"] }, 50 - "gap-40": { gap: spacing["40"] }, 51 - "gap-44": { gap: spacing["44"] }, 52 - "gap-48": { gap: spacing["48"] }, 53 - "gap-52": { gap: spacing["52"] }, 54 - "gap-56": { gap: spacing["56"] }, 55 - "gap-60": { gap: spacing["60"] }, 56 - "gap-64": { gap: spacing["64"] }, 57 - "gap-72": { gap: spacing["72"] }, 58 - "gap-80": { gap: spacing["80"] }, 59 - "gap-96": { gap: spacing["96"] }, 60 - }); 61 - 62 - export interface FlexProps extends Omit< 63 - React.ComponentProps<"div">, 64 - "style" | "className" 65 - > { 66 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 67 - /** 68 - * The direction of the flex container. 69 - * @default "row" 70 - * @type "row" | "row-reverse" | "column" | "column-reverse" 71 - * @see https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction 72 - */ 73 - direction?: "row" | "row-reverse" | "column" | "column-reverse"; 74 - /** 75 - * The flex wrap of the flex container. 76 - * @default false 77 - * @type "nowrap" | "wrap" | "wrap-reverse" 78 - * @see https://developer.mozilla.org/en-US/docs/Web/CSS/flex-wrap 79 - */ 80 - wrap?: boolean | "reverse"; 81 - /** 82 - * The flex justify content of the flex container. 83 - * @default "start" 84 - * @type "start" | "end" | "center" | "between" | "around" | "evenly" 85 - * @see https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content 86 - */ 87 - justify?: "start" | "end" | "center" | "between" | "around" | "evenly"; 88 - /** 89 - * The flex align items of the flex container. 90 - * @default "stretch" 91 - * @type "stretch" | "flex-start" | "flex-end" | "center" | "baseline" 92 - * @see https://developer.mozilla.org/en-US/docs/Web/CSS/align-items 93 - */ 94 - align?: "stretch" | "start" | "end" | "center" | "baseline"; 95 - /** 96 - * The gap of the flex container. 97 - * @default "0" 98 - * @type "0" | "0.5" | "1" | "1.5" | "2" | "2.5" | "3" | "3.5" | "4" | "5" | "6" | "7" | "8" | "9" | "10" | "11" | "12" | "14" | "16" | "20" | "24" | "28" | "32" | "36" | "40" | "44" | "48" | "52" | "56" | "60" | "64" | "72" | "80" | "96" 99 - * @see https://developer.mozilla.org/en-US/docs/Web/CSS/gap 100 - */ 101 - gap?: Spacing; 102 - /** 103 - * Whether the flex container is inline. 104 - * @default false 105 - * @type boolean 106 - * @see https://developer.mozilla.org/en-US/docs/Web/CSS/display 107 - */ 108 - inline?: boolean; 109 - } 110 - 111 - export const Flex = ({ 112 - style, 113 - direction, 114 - wrap, 115 - justify, 116 - align, 117 - gap, 118 - inline, 119 - ...props 120 - }: FlexProps) => { 121 - return ( 122 - <div 123 - {...props} 124 - {...stylex.props( 125 - inline ? styles.inline : styles.base, 126 - direction === "row" && styles.row, 127 - direction === "row-reverse" && styles["row-reverse"], 128 - direction === "column" && styles.column, 129 - direction === "column-reverse" && styles["column-reverse"], 130 - 131 - wrap && styles.wrap, 132 - wrap === "reverse" && styles["wrap-reverse"], 133 - 134 - justify === "start" && styles["justify-start"], 135 - justify === "end" && styles["justify-end"], 136 - justify === "center" && styles["justify-center"], 137 - justify === "between" && styles["justify-between"], 138 - justify === "around" && styles["justify-around"], 139 - justify === "evenly" && styles["justify-evenly"], 140 - 141 - align === "stretch" && styles["align-stretch"], 142 - align === "start" && styles["align-start"], 143 - align === "end" && styles["align-end"], 144 - align === "center" && styles["align-center"], 145 - align === "baseline" && styles["align-baseline"], 146 - 147 - typeof gap === "string" && styles[`gap-${gap}` as keyof typeof styles], 148 - 149 - style, 150 - )} 151 - /> 152 - ); 153 - };
-153
apps/example/src/components/flex/index.tsx
··· 1 - import * as stylex from "@stylexjs/stylex"; 2 - 3 - import type { Spacing } from "../theme/spacing.stylex"; 4 - 5 - import { spacing } from "../theme/spacing.stylex"; 6 - 7 - const styles = stylex.create({ 8 - base: { display: "flex" }, 9 - inline: { display: "inline-flex" }, 10 - row: { flexDirection: "row" }, 11 - "row-reverse": { flexDirection: "row-reverse" }, 12 - column: { flexDirection: "column" }, 13 - "column-reverse": { flexDirection: "column-reverse" }, 14 - wrap: { flexWrap: "wrap" }, 15 - "wrap-reverse": { flexWrap: "wrap-reverse" }, 16 - "justify-start": { justifyContent: "flex-start" }, 17 - "justify-end": { justifyContent: "flex-end" }, 18 - "justify-center": { justifyContent: "center" }, 19 - "justify-between": { justifyContent: "space-between" }, 20 - "justify-around": { justifyContent: "space-around" }, 21 - "justify-evenly": { justifyContent: "space-evenly" }, 22 - "align-stretch": { alignItems: "stretch" }, 23 - "align-start": { alignItems: "flex-start" }, 24 - "align-end": { alignItems: "flex-end" }, 25 - "align-center": { alignItems: "center" }, 26 - "align-baseline": { alignItems: "baseline" }, 27 - "gap-0.5": { gap: spacing["0.5"] }, 28 - "gap-1": { gap: spacing["1"] }, 29 - "gap-1.5": { gap: spacing["1.5"] }, 30 - "gap-2": { gap: spacing["2"] }, 31 - "gap-2.5": { gap: spacing["2.5"] }, 32 - "gap-3": { gap: spacing["3"] }, 33 - "gap-3.5": { gap: spacing["3.5"] }, 34 - "gap-4": { gap: spacing["4"] }, 35 - "gap-5": { gap: spacing["5"] }, 36 - "gap-6": { gap: spacing["6"] }, 37 - "gap-7": { gap: spacing["7"] }, 38 - "gap-8": { gap: spacing["8"] }, 39 - "gap-9": { gap: spacing["9"] }, 40 - "gap-10": { gap: spacing["10"] }, 41 - "gap-11": { gap: spacing["11"] }, 42 - "gap-12": { gap: spacing["12"] }, 43 - "gap-14": { gap: spacing["14"] }, 44 - "gap-16": { gap: spacing["16"] }, 45 - "gap-20": { gap: spacing["20"] }, 46 - "gap-24": { gap: spacing["24"] }, 47 - "gap-28": { gap: spacing["28"] }, 48 - "gap-32": { gap: spacing["32"] }, 49 - "gap-36": { gap: spacing["36"] }, 50 - "gap-40": { gap: spacing["40"] }, 51 - "gap-44": { gap: spacing["44"] }, 52 - "gap-48": { gap: spacing["48"] }, 53 - "gap-52": { gap: spacing["52"] }, 54 - "gap-56": { gap: spacing["56"] }, 55 - "gap-60": { gap: spacing["60"] }, 56 - "gap-64": { gap: spacing["64"] }, 57 - "gap-72": { gap: spacing["72"] }, 58 - "gap-80": { gap: spacing["80"] }, 59 - "gap-96": { gap: spacing["96"] }, 60 - }); 61 - 62 - export interface FlexProps extends Omit< 63 - React.ComponentProps<"div">, 64 - "style" | "className" 65 - > { 66 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 67 - /** 68 - * The direction of the flex container. 69 - * @default "row" 70 - * @type "row" | "row-reverse" | "column" | "column-reverse" 71 - * @see https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction 72 - */ 73 - direction?: "row" | "row-reverse" | "column" | "column-reverse"; 74 - /** 75 - * The flex wrap of the flex container. 76 - * @default false 77 - * @type "nowrap" | "wrap" | "wrap-reverse" 78 - * @see https://developer.mozilla.org/en-US/docs/Web/CSS/flex-wrap 79 - */ 80 - wrap?: boolean | "reverse"; 81 - /** 82 - * The flex justify content of the flex container. 83 - * @default "start" 84 - * @type "start" | "end" | "center" | "between" | "around" | "evenly" 85 - * @see https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content 86 - */ 87 - justify?: "start" | "end" | "center" | "between" | "around" | "evenly"; 88 - /** 89 - * The flex align items of the flex container. 90 - * @default "stretch" 91 - * @type "stretch" | "flex-start" | "flex-end" | "center" | "baseline" 92 - * @see https://developer.mozilla.org/en-US/docs/Web/CSS/align-items 93 - */ 94 - align?: "stretch" | "start" | "end" | "center" | "baseline"; 95 - /** 96 - * The gap of the flex container. 97 - * @default "0" 98 - * @type "0" | "0.5" | "1" | "1.5" | "2" | "2.5" | "3" | "3.5" | "4" | "5" | "6" | "7" | "8" | "9" | "10" | "11" | "12" | "14" | "16" | "20" | "24" | "28" | "32" | "36" | "40" | "44" | "48" | "52" | "56" | "60" | "64" | "72" | "80" | "96" 99 - * @see https://developer.mozilla.org/en-US/docs/Web/CSS/gap 100 - */ 101 - gap?: Spacing; 102 - /** 103 - * Whether the flex container is inline. 104 - * @default false 105 - * @type boolean 106 - * @see https://developer.mozilla.org/en-US/docs/Web/CSS/display 107 - */ 108 - inline?: boolean; 109 - } 110 - 111 - export const Flex = ({ 112 - style, 113 - direction, 114 - wrap, 115 - justify, 116 - align, 117 - gap, 118 - inline, 119 - ...props 120 - }: FlexProps) => { 121 - return ( 122 - <div 123 - {...props} 124 - {...stylex.props( 125 - inline ? styles.inline : styles.base, 126 - direction === "row" && styles.row, 127 - direction === "row-reverse" && styles["row-reverse"], 128 - direction === "column" && styles.column, 129 - direction === "column-reverse" && styles["column-reverse"], 130 - 131 - wrap && styles.wrap, 132 - wrap === "reverse" && styles["wrap-reverse"], 133 - 134 - justify === "start" && styles["justify-start"], 135 - justify === "end" && styles["justify-end"], 136 - justify === "center" && styles["justify-center"], 137 - justify === "between" && styles["justify-between"], 138 - justify === "around" && styles["justify-around"], 139 - justify === "evenly" && styles["justify-evenly"], 140 - 141 - align === "stretch" && styles["align-stretch"], 142 - align === "start" && styles["align-start"], 143 - align === "end" && styles["align-end"], 144 - align === "center" && styles["align-center"], 145 - align === "baseline" && styles["align-baseline"], 146 - 147 - typeof gap === "string" && styles[`gap-${gap}` as keyof typeof styles], 148 - 149 - style, 150 - )} 151 - /> 152 - ); 153 - };
-53
apps/example/src/components/icon-button/index.tsx
··· 1 - "use client"; 2 - 3 - import type { ButtonProps as AriaButtonProps } from "react-aria-components"; 4 - 5 - import * as stylex from "@stylexjs/stylex"; 6 - import { use } from "react"; 7 - 8 - import type { ButtonVariant, Size } from "../types"; 9 - 10 - import { Button } from "../button"; 11 - import { SizeContext } from "../context"; 12 - import { spacing } from "../theme/spacing.stylex"; 13 - import { Tooltip } from "../tooltip"; 14 - 15 - const styles = stylex.create({ 16 - sm: { 17 - height: spacing["7"], 18 - width: spacing["7"], 19 - }, 20 - md: { 21 - height: spacing["8"], 22 - width: spacing["8"], 23 - }, 24 - lg: { 25 - height: spacing["10"], 26 - width: spacing["10"], 27 - }, 28 - }); 29 - 30 - interface IconButtonProps extends Omit<AriaButtonProps, "className" | "style"> { 31 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 32 - variant?: ButtonVariant; 33 - size?: Size; 34 - label: string; 35 - } 36 - 37 - export const IconButton = ({ 38 - children, 39 - size: sizeProp, 40 - label, 41 - style, 42 - ...props 43 - }: IconButtonProps) => { 44 - const size = sizeProp || use(SizeContext); 45 - 46 - return ( 47 - <Tooltip text={label}> 48 - <Button size={size} style={[styles[size], style]} {...props}> 49 - {children} 50 - </Button> 51 - </Tooltip> 52 - ); 53 - };
-89
apps/example/src/components/label/index.tsx
··· 1 - import type { 2 - LabelProps as AriaLabelProps, 3 - TextProps, 4 - } from "react-aria-components"; 5 - 6 - import * as stylex from "@stylexjs/stylex"; 7 - import { use } from "react"; 8 - import { Label as AriaLabel, Text } from "react-aria-components"; 9 - 10 - import type { Size } from "../types"; 11 - 12 - import { SizeContext } from "../context"; 13 - import { gray } from "../theme/semantic-color.stylex"; 14 - import { fontSize, fontWeight, lineHeight } from "../theme/typography.stylex"; 15 - 16 - const styles = stylex.create({ 17 - label: { 18 - fontWeight: fontWeight["semibold"], 19 - }, 20 - sm: { 21 - fontSize: fontSize["xs"], 22 - lineHeight: lineHeight["xs"], 23 - }, 24 - md: { 25 - fontSize: fontSize["sm"], 26 - lineHeight: lineHeight["sm"], 27 - }, 28 - lg: { 29 - fontSize: fontSize["base"], 30 - lineHeight: lineHeight["base"], 31 - }, 32 - description: { 33 - color: gray.textDim, 34 - fontSize: fontSize["sm"], 35 - lineHeight: lineHeight["sm"], 36 - }, 37 - descriptionSm: { 38 - fontSize: fontSize["xs"], 39 - lineHeight: lineHeight["xs"], 40 - }, 41 - }); 42 - 43 - export interface LabelProps extends Omit< 44 - AriaLabelProps, 45 - "style" | "className" 46 - > { 47 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 48 - size?: Size; 49 - } 50 - 51 - export function Label({ style, size: sizeProp, ...props }: LabelProps) { 52 - const size = sizeProp || use(SizeContext); 53 - 54 - return ( 55 - <AriaLabel 56 - {...props} 57 - {...stylex.props(styles[size], styles.label, style)} 58 - /> 59 - ); 60 - } 61 - 62 - export interface DescriptionProps extends Omit< 63 - TextProps, 64 - "style" | "className" 65 - > { 66 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 67 - size?: Size; 68 - } 69 - 70 - export function Description({ 71 - style, 72 - size: sizeProp, 73 - ...props 74 - }: DescriptionProps) { 75 - const size = sizeProp || use(SizeContext); 76 - 77 - return ( 78 - <Text 79 - slot="description" 80 - {...stylex.props( 81 - styles.description, 82 - gray.textDim, 83 - size === "sm" && styles.descriptionSm, 84 - style, 85 - )} 86 - {...props} 87 - /> 88 - ); 89 - }
-37
apps/example/src/components/link/index.tsx
··· 1 - import type { LinkProps as AriaLinkProps } from "react-aria-components"; 2 - 3 - import * as stylex from "@stylexjs/stylex"; 4 - import { use } from "react"; 5 - import { Link as AriaLink } from "react-aria-components"; 6 - 7 - import { blue } from "../theme/colors.stylex"; 8 - import { fontFamily, fontWeight } from "../theme/typography.stylex"; 9 - import { LinkContext } from "./link-context"; 10 - 11 - const styles = stylex.create({ 12 - link: { 13 - textDecoration: { 14 - default: "none", 15 - ":hover": "underline", 16 - }, 17 - color: { 18 - default: blue.text2, 19 - ":visited": blue.text1, 20 - }, 21 - cursor: "pointer", 22 - fontFamily: fontFamily["sans"], 23 - fontWeight: fontWeight["normal"], 24 - }, 25 - }); 26 - 27 - export interface LinkProps extends Omit<AriaLinkProps, "style" | "className"> { 28 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 29 - } 30 - 31 - export function Link({ style, ...props }: LinkProps) { 32 - const context = use(LinkContext); 33 - 34 - return ( 35 - <AriaLink {...props} {...stylex.props(styles.link, context.style, style)} /> 36 - ); 37 - }
-176
apps/example/src/components/listbox/index.tsx
··· 1 - import type { 2 - ListBoxItemProps as AriaListBoxItemProps, 3 - ListBoxProps as AriaListBoxProps, 4 - ListBoxSectionProps as AriaListBoxSectionProps, 5 - SeparatorProps, 6 - } from "react-aria-components"; 7 - 8 - import * as stylex from "@stylexjs/stylex"; 9 - import { Check } from "lucide-react"; 10 - import { use } from "react"; 11 - import { 12 - ListBox as AriaListBox, 13 - ListBoxItem as AriaListBoxItem, 14 - ListBoxSection as AriaListBoxSection, 15 - Header, 16 - } from "react-aria-components"; 17 - 18 - import type { Size } from "../types"; 19 - 20 - import { SizeContext } from "../context"; 21 - import { Separator } from "../separator"; 22 - import { gray } from "../theme/semantic-color.stylex"; 23 - import { spacing } from "../theme/spacing.stylex"; 24 - import { typeramp } from "../theme/typography.stylex"; 25 - import { useListBoxItemStyles } from "../theme/useListBoxItemStyles"; 26 - 27 - const styles = stylex.create({ 28 - listBox: { 29 - outline: "none", 30 - }, 31 - sectionLabel: { 32 - alignItems: "center", 33 - boxSizing: "border-box", 34 - display: "flex", 35 - paddingBottom: spacing["1"], 36 - paddingLeft: spacing["3"], 37 - paddingRight: spacing["3"], 38 - paddingTop: spacing["1"], 39 - }, 40 - smSectionLabel: { 41 - height: spacing["7"], 42 - }, 43 - mdSectionLabel: { 44 - height: spacing["7"], 45 - }, 46 - lgSectionLabel: { 47 - height: spacing["9"], 48 - }, 49 - separator: { 50 - marginBottom: spacing["1.5"], 51 - marginTop: spacing["1.5"], 52 - }, 53 - }); 54 - 55 - export interface ListBoxProps<T extends object> extends Omit< 56 - AriaListBoxProps<T>, 57 - "style" | "className" 58 - > { 59 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 60 - size?: Size; 61 - items?: Iterable<T>; 62 - children: React.ReactNode | ((item: T) => React.ReactNode); 63 - } 64 - 65 - export function ListBox<T extends object>({ 66 - size: sizeProp, 67 - style, 68 - ...props 69 - }: ListBoxProps<T>) { 70 - const size = sizeProp || use(SizeContext); 71 - 72 - return ( 73 - <SizeContext value={size}> 74 - <AriaListBox {...stylex.props(styles.listBox, style)} {...props} /> 75 - </SizeContext> 76 - ); 77 - } 78 - 79 - export interface ListBoxItemProps extends Omit< 80 - AriaListBoxItemProps, 81 - "style" | "className" | "children" 82 - > { 83 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 84 - children: React.ReactNode; 85 - prefix?: React.ReactNode; 86 - suffix?: React.ReactNode; 87 - } 88 - 89 - export function ListBoxItem({ 90 - style, 91 - children, 92 - prefix, 93 - suffix, 94 - ...props 95 - }: ListBoxItemProps) { 96 - const listBoxItemStyles = useListBoxItemStyles(); 97 - 98 - return ( 99 - <AriaListBoxItem 100 - {...props} 101 - value={props.value || { id: props.id, label: children }} 102 - textValue={ 103 - props.textValue || (typeof children === "string" ? children : undefined) 104 - } 105 - {...stylex.props(listBoxItemStyles.wrapper, style)} 106 - > 107 - {({ isSelected }) => ( 108 - <div {...stylex.props(listBoxItemStyles.inner)}> 109 - {prefix !== null && ( 110 - <div {...stylex.props(listBoxItemStyles.addon)}>{prefix}</div> 111 - )} 112 - <div {...stylex.props(listBoxItemStyles.label)}>{children}</div> 113 - {suffix !== null && ( 114 - <div {...stylex.props(listBoxItemStyles.addon)}>{suffix}</div> 115 - )} 116 - {isSelected && ( 117 - <Check size={16} {...stylex.props(listBoxItemStyles.check)} /> 118 - )} 119 - </div> 120 - )} 121 - </AriaListBoxItem> 122 - ); 123 - } 124 - 125 - export interface ListBoxSectionProps<T extends object> extends Omit< 126 - AriaListBoxSectionProps<T>, 127 - "style" | "className" 128 - > { 129 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 130 - children: React.ReactNode; 131 - } 132 - 133 - export function ListBoxSection<T extends object>({ 134 - style, 135 - ...props 136 - }: ListBoxSectionProps<T>) { 137 - return <AriaListBoxSection {...props} {...stylex.props(style)} />; 138 - } 139 - 140 - export interface ListBoxSeparatorProps extends Omit< 141 - SeparatorProps, 142 - "style" | "className" 143 - > { 144 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 145 - } 146 - 147 - export function ListBoxSeparator({ style, ...props }: ListBoxSeparatorProps) { 148 - return <Separator {...props} style={[styles.separator, style]} />; 149 - } 150 - 151 - export interface ListBoxSectionHeaderProps extends Omit< 152 - React.HTMLAttributes<HTMLElement>, 153 - "style" | "className" 154 - > { 155 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 156 - } 157 - 158 - export function ListBoxSectionHeader({ 159 - style, 160 - ...props 161 - }: ListBoxSectionHeaderProps) { 162 - const size = use(SizeContext); 163 - 164 - return ( 165 - <Header 166 - {...props} 167 - {...stylex.props( 168 - typeramp.sublabel, 169 - styles.sectionLabel, 170 - gray.textDim, 171 - styles[`${size}SectionLabel`], 172 - style, 173 - )} 174 - /> 175 - ); 176 - }
-202
apps/example/src/components/menu/index.tsx
··· 1 - import type { 2 - MenuItemProps as AriaMenuItemProps, 3 - MenuProps as AriaMenuProps, 4 - MenuSectionProps as AriaMenuSectionProps, 5 - MenuTriggerProps, 6 - PopoverProps, 7 - SubmenuTriggerProps, 8 - } from "react-aria-components"; 9 - 10 - import * as stylex from "@stylexjs/stylex"; 11 - import { Check, ChevronRight } from "lucide-react"; 12 - import { use } from "react"; 13 - import { 14 - Menu as AriaMenu, 15 - MenuItem as AriaMenuItem, 16 - MenuSection as AriaMenuSection, 17 - MenuTrigger, 18 - Popover, 19 - SubmenuTrigger, 20 - } from "react-aria-components"; 21 - 22 - import type { Size } from "../types"; 23 - 24 - import { SizeContext } from "../context"; 25 - import { useListBoxItemStyles } from "../theme/useListBoxItemStyles"; 26 - import { usePopoverStyles } from "../theme/usePopoverStyles"; 27 - 28 - export interface MenuProps<T extends object> 29 - extends 30 - Omit<MenuTriggerProps, "trigger" | "children">, 31 - Omit<AriaMenuProps<T>, "children" | "className" | "style">, 32 - Pick< 33 - PopoverProps, 34 - | "shouldCloseOnInteractOutside" 35 - | "shouldFlip" 36 - | "shouldUpdatePosition" 37 - | "placement" 38 - > { 39 - trigger: React.ReactNode; 40 - items?: Iterable<T>; 41 - children: React.ReactNode | ((item: T) => React.ReactNode); 42 - size?: Size; 43 - } 44 - 45 - export function Menu<T extends object>({ 46 - trigger, 47 - size: sizeProp, 48 - defaultOpen, 49 - isOpen, 50 - onOpenChange, 51 - shouldCloseOnInteractOutside, 52 - shouldFlip, 53 - shouldUpdatePosition, 54 - placement, 55 - ...props 56 - }: MenuProps<T>) { 57 - const popoverStyles = usePopoverStyles(); 58 - const size = sizeProp || use(SizeContext); 59 - 60 - return ( 61 - <SizeContext value={size}> 62 - <MenuTrigger 63 - defaultOpen={defaultOpen} 64 - isOpen={isOpen} 65 - onOpenChange={onOpenChange} 66 - > 67 - {trigger} 68 - <Popover 69 - containerPadding={8} 70 - shouldCloseOnInteractOutside={shouldCloseOnInteractOutside} 71 - shouldFlip={shouldFlip} 72 - shouldUpdatePosition={shouldUpdatePosition} 73 - placement={placement} 74 - > 75 - <AriaMenu {...props} {...stylex.props(popoverStyles)} /> 76 - </Popover> 77 - </MenuTrigger> 78 - </SizeContext> 79 - ); 80 - } 81 - 82 - export interface SubMenuProps<T extends object> 83 - extends 84 - Omit<SubmenuTriggerProps, "trigger" | "children">, 85 - Omit<AriaMenuProps<T>, "children" | "className" | "style">, 86 - Pick< 87 - PopoverProps, 88 - | "shouldCloseOnInteractOutside" 89 - | "shouldFlip" 90 - | "shouldUpdatePosition" 91 - | "placement" 92 - > { 93 - trigger: React.ReactElement<MenuTriggerProps>; 94 - children: React.ReactNode | ((item: T) => React.ReactNode); 95 - items?: Iterable<T>; 96 - size?: Size; 97 - } 98 - 99 - export function SubMenu<T extends object>({ 100 - trigger, 101 - delay, 102 - shouldCloseOnInteractOutside, 103 - shouldFlip, 104 - shouldUpdatePosition, 105 - placement, 106 - ...props 107 - }: SubMenuProps<T>) { 108 - const popoverStyles = usePopoverStyles(); 109 - 110 - return ( 111 - <SubmenuTrigger delay={delay}> 112 - {trigger} 113 - <Popover 114 - shouldCloseOnInteractOutside={shouldCloseOnInteractOutside} 115 - shouldFlip={shouldFlip} 116 - shouldUpdatePosition={shouldUpdatePosition} 117 - placement={placement} 118 - containerPadding={8} 119 - offset={-8} 120 - > 121 - <AriaMenu {...props} {...stylex.props(popoverStyles)} /> 122 - </Popover> 123 - </SubmenuTrigger> 124 - ); 125 - } 126 - 127 - export interface MenuSectionProps<T extends object> extends Omit< 128 - AriaMenuSectionProps<T>, 129 - "style" | "className" 130 - > { 131 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 132 - children: React.ReactNode; 133 - } 134 - 135 - export function MenuSection<T extends object>({ 136 - style, 137 - ...props 138 - }: MenuSectionProps<T>) { 139 - return <AriaMenuSection {...props} {...stylex.props(style)} />; 140 - } 141 - 142 - export interface MenuItemProps extends Omit< 143 - AriaMenuItemProps, 144 - "style" | "className" | "children" 145 - > { 146 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 147 - children: React.ReactNode; 148 - prefix?: React.ReactNode; 149 - suffix?: React.ReactNode; 150 - } 151 - 152 - export function MenuItem({ 153 - style, 154 - children, 155 - prefix, 156 - suffix, 157 - ...props 158 - }: MenuItemProps) { 159 - const menuItemStyles = useListBoxItemStyles(); 160 - 161 - return ( 162 - <AriaMenuItem 163 - {...props} 164 - textValue={ 165 - props.textValue || (typeof children === "string" ? children : undefined) 166 - } 167 - {...stylex.props(menuItemStyles.wrapper, style)} 168 - > 169 - {({ isSelected, hasSubmenu }) => ( 170 - <div {...stylex.props(menuItemStyles.inner)}> 171 - {prefix !== null && ( 172 - <div {...stylex.props(menuItemStyles.addon)}>{prefix}</div> 173 - )} 174 - <div {...stylex.props(menuItemStyles.label)}>{children}</div> 175 - {suffix !== null && ( 176 - <div {...stylex.props(menuItemStyles.addon)}>{suffix}</div> 177 - )} 178 - {isSelected && ( 179 - <div {...stylex.props(menuItemStyles.addon)}> 180 - <Check size={16} {...stylex.props(menuItemStyles.check)} /> 181 - </div> 182 - )} 183 - {hasSubmenu && ( 184 - <div {...stylex.props(menuItemStyles.addon)}> 185 - <ChevronRight size={16} /> 186 - </div> 187 - )} 188 - </div> 189 - )} 190 - </AriaMenuItem> 191 - ); 192 - } 193 - 194 - export type { 195 - ListBoxSectionHeaderProps as MenuSectionHeaderProps, 196 - ListBoxSeparatorProps as MenuSeparatorProps, 197 - } from "../listbox"; 198 - 199 - export { 200 - ListBoxSectionHeader as MenuSectionHeader, 201 - ListBoxSeparator as MenuSeparator, 202 - } from "../listbox";
-126
apps/example/src/components/number-field/index.tsx
··· 1 - import type { 2 - NumberFieldProps as AriaNumberFieldProps, 3 - InputProps, 4 - ValidationResult, 5 - } from "react-aria-components"; 6 - 7 - import * as stylex from "@stylexjs/stylex"; 8 - import { Minus, Plus } from "lucide-react"; 9 - import { useRef } from "react"; 10 - import { 11 - NumberField as AriaNumberField, 12 - Button, 13 - FieldError, 14 - Group, 15 - Input, 16 - } from "react-aria-components"; 17 - 18 - import type { Size } from "../types"; 19 - 20 - import { Description, Label } from "../label"; 21 - import { slate } from "../theme/colors.stylex"; 22 - import { gray } from "../theme/semantic-color.stylex"; 23 - import { spacing } from "../theme/spacing.stylex"; 24 - import { useInputStyles } from "../theme/useInputStyles"; 25 - 26 - const styles = stylex.create({ 27 - buttons: { 28 - display: "flex", 29 - }, 30 - button: { 31 - borderWidth: 0, 32 - alignItems: "center", 33 - display: "flex", 34 - flexGrow: 1, 35 - justifyContent: "center", 36 - borderBottomWidth: 0, 37 - borderLeftStyle: "solid", 38 - borderLeftWidth: 1, 39 - borderRightWidth: 0, 40 - borderTopWidth: 0, 41 - minHeight: 0, 42 - 43 - // eslint-disable-next-line @stylexjs/no-legacy-contextual-styles, @stylexjs/valid-styles 44 - ":is(*) svg": { 45 - flexShrink: 0, 46 - pointerEvents: "none", 47 - height: spacing["4"], 48 - width: spacing["4"], 49 - }, 50 - 51 - color: { 52 - default: slate.text2, 53 - ":disabled": slate.text1, 54 - }, 55 - }, 56 - }); 57 - 58 - export interface NumberFieldProps 59 - extends 60 - Omit<AriaNumberFieldProps, "style" | "className">, 61 - Pick<InputProps, "placeholder"> { 62 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 63 - label?: React.ReactNode; 64 - description?: string; 65 - errorMessage?: string | ((validation: ValidationResult) => string); 66 - size?: Size; 67 - prefix?: React.ReactNode; 68 - suffix?: React.ReactNode; 69 - } 70 - 71 - export function NumberField({ 72 - label, 73 - description, 74 - errorMessage, 75 - style, 76 - size, 77 - prefix, 78 - suffix, 79 - placeholder, 80 - ...props 81 - }: NumberFieldProps) { 82 - const inputRef = useRef<HTMLInputElement>(null); 83 - const inputStyles = useInputStyles({ size }); 84 - const buttonStyles = stylex.props( 85 - styles.button, 86 - gray.borderInteractive, 87 - gray.bgAction, 88 - ); 89 - 90 - return ( 91 - <AriaNumberField {...props} {...stylex.props(inputStyles.field, style)}> 92 - <Label size={size}>{label}</Label> 93 - {/* 94 - This onClick is specifically for mouse users not clicking directly on the input. 95 - A keyboard user would not encounter the same issue. 96 - */} 97 - {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 98 - <div 99 - {...stylex.props(inputStyles.wrapper)} 100 - onClick={() => inputRef.current?.focus()} 101 - > 102 - {prefix !== null && ( 103 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 104 - )} 105 - <Input 106 - placeholder={placeholder} 107 - ref={inputRef} 108 - {...stylex.props(inputStyles.input)} 109 - /> 110 - {suffix !== null && ( 111 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 112 - )} 113 - <Group {...stylex.props(styles.buttons)}> 114 - <Button slot="decrement" {...buttonStyles}> 115 - <Minus /> 116 - </Button> 117 - <Button slot="increment" {...buttonStyles}> 118 - <Plus /> 119 - </Button> 120 - </Group> 121 - </div> 122 - {description && <Description size={size}>{description}</Description>} 123 - <FieldError>{errorMessage}</FieldError> 124 - </AriaNumberField> 125 - ); 126 - }
-86
apps/example/src/components/popover/index.tsx
··· 1 - "use client"; 2 - 3 - import type { 4 - PopoverProps as AriaPopoverProps, 5 - DialogTriggerProps, 6 - } from "react-aria-components"; 7 - 8 - import * as stylex from "@stylexjs/stylex"; 9 - import { 10 - Popover as AriaPopover, 11 - Dialog, 12 - DialogTrigger, 13 - OverlayArrow, 14 - } from "react-aria-components"; 15 - 16 - import { slate } from "../theme/colors.stylex"; 17 - import { spacing } from "../theme/spacing.stylex"; 18 - import { usePopoverStyles } from "../theme/usePopoverStyles"; 19 - 20 - const styles = stylex.create({ 21 - wrapper: { 22 - filter: `drop-shadow(-0.5px -0.5px 0 ${slate.border2}) drop-shadow(0.5px -0.5px 0 ${slate.border2}) drop-shadow(0.5px 0.5px 0 ${slate.border2}) drop-shadow(-0.5px 0.5px 0 ${slate.border2}) drop-shadow(0px 1px 3px rgb(0 0 0 / 0.1)) drop-shadow(0px -1px 3px rgb(0 0 0 / 0.1))`, 23 - }, 24 - content: { 25 - borderWidth: 0, 26 - boxShadow: "none", 27 - position: "relative", 28 - paddingBottom: spacing["2"], 29 - paddingLeft: spacing["2"], 30 - paddingRight: spacing["2"], 31 - paddingTop: spacing["2"], 32 - }, 33 - caret: {}, 34 - arrow: { 35 - backgroundColor: slate.bg2, 36 - transform: { 37 - [":is([data-placement=bottom] *)"]: "rotate(180deg)", 38 - [":is([data-placement=left] *)"]: "rotate(90deg)", 39 - [":is([data-placement=right] *)"]: "rotate(-90deg)", 40 - [":is([data-placement=top] *)"]: "translateY(-50%) rotate(-45deg)", 41 - }, 42 - zIndex: 0, 43 - height: spacing["2"], 44 - width: spacing["2"], 45 - }, 46 - }); 47 - interface TooltipProps 48 - extends 49 - DialogTriggerProps, 50 - Pick<AriaPopoverProps, "crossOffset" | "placement" | "shouldFlip"> { 51 - trigger: React.ReactNode; 52 - children: React.ReactNode; 53 - } 54 - 55 - export const Popover = ({ 56 - trigger, 57 - children, 58 - defaultOpen, 59 - isOpen, 60 - onOpenChange, 61 - ...popoverProps 62 - }: TooltipProps) => { 63 - const popoverStyles = usePopoverStyles(); 64 - 65 - return ( 66 - <DialogTrigger 67 - {...({ isOpen, onOpenChange, defaultOpen } as DialogTriggerProps)} 68 - > 69 - {trigger} 70 - 71 - <AriaPopover 72 - {...stylex.props(styles.wrapper)} 73 - {...popoverProps} 74 - offset={8} 75 - containerPadding={8} 76 - > 77 - <OverlayArrow {...stylex.props(styles.caret)}> 78 - <div {...stylex.props(styles.arrow)} /> 79 - </OverlayArrow> 80 - <Dialog {...stylex.props(popoverStyles, styles.content)}> 81 - {children} 82 - </Dialog> 83 - </AriaPopover> 84 - </DialogTrigger> 85 - ); 86 - };
-154
apps/example/src/components/radio/index.tsx
··· 1 - import type { 2 - RadioGroupProps as AriaRadioGroupProps, 3 - RadioProps as AriaRadioProps, 4 - ValidationResult, 5 - } from "react-aria-components"; 6 - 7 - import * as stylex from "@stylexjs/stylex"; 8 - import { 9 - Radio as AriaRadio, 10 - RadioGroup as AriaRadioGroup, 11 - FieldError, 12 - SelectionIndicator, 13 - } from "react-aria-components"; 14 - 15 - import type { Size } from "../types"; 16 - 17 - import { Flex } from "../flex"; 18 - import { Description, Label } from "../label"; 19 - import { animationDuration } from "../theme/animations.stylex"; 20 - import { radius } from "../theme/radius.stylex"; 21 - import { gray, primary } from "../theme/semantic-color.stylex"; 22 - import { spacing } from "../theme/spacing.stylex"; 23 - import { fontFamily, fontSize, lineHeight } from "../theme/typography.stylex"; 24 - 25 - const scaleIn = stylex.keyframes({ 26 - "0%": { 27 - transform: "translate(-50%, -50%) scale(0)", 28 - }, 29 - "100%": { 30 - transform: "translate(-50%, -50%) scale(1)", 31 - }, 32 - }); 33 - 34 - const styles = stylex.create({ 35 - wrapper: { 36 - gap: spacing["2.5"], 37 - alignItems: { 38 - default: "center", 39 - ":has(p)": "flex-start", 40 - }, 41 - display: "flex", 42 - 43 - fontFamily: fontFamily["sans"], 44 - fontSize: fontSize["sm"], 45 - lineHeight: lineHeight["sm"], 46 - opacity: { ":is([data-disabled])": 0.5 }, 47 - }, 48 - radio: { 49 - alignItems: "center", 50 - display: "flex", 51 - justifyContent: "center", 52 - 53 - borderRadius: radius["full"], 54 - borderWidth: 2, 55 - position: "relative", 56 - height: spacing["4"], 57 - width: spacing["4"], 58 - 59 - transitionDuration: animationDuration.fast, 60 - transitionProperty: "background-color, border-color, color", 61 - transitionTimingFunction: "ease-in-out", 62 - }, 63 - selectionIndicator: { 64 - borderRadius: radius["full"], 65 - backgroundColor: "white", 66 - height: spacing["2"], 67 - width: spacing["2"], 68 - 69 - position: "absolute", 70 - transform: "translate(-50%, -50%)", 71 - left: "50%", 72 - top: "50%", 73 - 74 - animationDuration: animationDuration.fast, 75 - animationFillMode: "forwards", 76 - animationName: scaleIn, 77 - animationTimingFunction: "ease-in-out", 78 - }, 79 - checked: { 80 - color: "white", 81 - }, 82 - group: { 83 - gap: spacing["3"], 84 - display: "flex", 85 - flexDirection: "column", 86 - }, 87 - }); 88 - 89 - interface RadioGroupProps extends Omit< 90 - AriaRadioGroupProps, 91 - "children" | "style" | "className" 92 - > { 93 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 94 - children?: React.ReactNode; 95 - label?: React.ReactNode; 96 - description?: string; 97 - errorMessage?: string | ((validation: ValidationResult) => string); 98 - size?: Size; 99 - } 100 - 101 - export function RadioGroup({ 102 - label, 103 - description, 104 - errorMessage, 105 - children, 106 - size, 107 - style, 108 - ...props 109 - }: RadioGroupProps) { 110 - return ( 111 - <AriaRadioGroup {...props} {...stylex.props(styles.group, style)}> 112 - {label !== null && <Label size={size}>{label}</Label>} 113 - <Flex direction="column" gap="2"> 114 - {children} 115 - </Flex> 116 - {description && <Description size={size}>{description}</Description>} 117 - <FieldError>{errorMessage}</FieldError> 118 - </AriaRadioGroup> 119 - ); 120 - } 121 - 122 - export interface RadioProps extends Omit< 123 - AriaRadioProps, 124 - "className" | "style" | "children" 125 - > { 126 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 127 - children?: React.ReactNode; 128 - } 129 - 130 - export function Radio({ children, style, ...props }: RadioProps) { 131 - return ( 132 - <AriaRadio {...props} {...stylex.props(styles.wrapper, style)}> 133 - {({ isSelected, isDisabled }) => ( 134 - <> 135 - <div 136 - {...stylex.props( 137 - styles.radio, 138 - isDisabled 139 - ? [gray.bgSolid, gray.border, styles.checked] 140 - : isSelected 141 - ? [primary.bgSolid, primary.borderInteractive, styles.checked] 142 - : [gray.borderInteractive], 143 - )} 144 - > 145 - <SelectionIndicator {...stylex.props(styles.selectionIndicator)} /> 146 - </div> 147 - <Flex direction="column" gap="1"> 148 - {children} 149 - </Flex> 150 - </> 151 - )} 152 - </AriaRadio> 153 - ); 154 - }
-117
apps/example/src/components/search-field/index.tsx
··· 1 - import type { 2 - SearchFieldProps as AriaSearchFieldProps, 3 - InputProps, 4 - ValidationResult, 5 - } from "react-aria-components"; 6 - 7 - import * as stylex from "@stylexjs/stylex"; 8 - import { SearchIcon, X } from "lucide-react"; 9 - import { useRef } from "react"; 10 - import { 11 - SearchField as AriaSearchField, 12 - FieldError, 13 - Input, 14 - } from "react-aria-components"; 15 - 16 - import type { Size } from "../types"; 17 - 18 - import { IconButton } from "../icon-button"; 19 - import { Description, Label } from "../label"; 20 - import { spacing } from "../theme/spacing.stylex"; 21 - import { useInputStyles } from "../theme/useInputStyles"; 22 - 23 - const styles = stylex.create({ 24 - wrapper: { 25 - position: "relative", 26 - }, 27 - clearButton: { 28 - position: "absolute", 29 - transform: "translateY(-50%)", 30 - right: 0, 31 - top: "50%", 32 - }, 33 - clearButtonPadding: { 34 - paddingRight: spacing["8"], 35 - }, 36 - }); 37 - 38 - export interface SearchFieldProps 39 - extends 40 - Omit<AriaSearchFieldProps, "style" | "className">, 41 - Pick<InputProps, "placeholder"> { 42 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 43 - label?: React.ReactNode; 44 - description?: string; 45 - errorMessage?: string | ((validation: ValidationResult) => string); 46 - size?: Size; 47 - prefix?: React.ReactNode; 48 - suffix?: React.ReactNode; 49 - } 50 - 51 - const defaultPrefix = <SearchIcon />; 52 - 53 - export function SearchField({ 54 - label, 55 - description, 56 - errorMessage, 57 - style, 58 - size, 59 - prefix = defaultPrefix, 60 - suffix, 61 - placeholder, 62 - ...props 63 - }: SearchFieldProps) { 64 - const inputRef = useRef<HTMLInputElement>(null); 65 - const inputStyles = useInputStyles({ size }); 66 - 67 - return ( 68 - <AriaSearchField {...props} {...stylex.props(inputStyles.field, style)}> 69 - {({ isEmpty }) => { 70 - return ( 71 - <> 72 - {label !== null && <Label size={size}>{label}</Label>} 73 - {/* 74 - This onClick is specifically for mouse users not clicking directly on the input. 75 - A keyboard user would not encounter the same issue. 76 - */} 77 - {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 78 - <div 79 - {...stylex.props(inputStyles.wrapper, styles.wrapper)} 80 - onClick={() => inputRef.current?.focus()} 81 - > 82 - {prefix !== null && ( 83 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 84 - )} 85 - <Input 86 - placeholder={placeholder} 87 - ref={inputRef} 88 - {...stylex.props( 89 - inputStyles.input, 90 - !isEmpty && styles.clearButtonPadding, 91 - )} 92 - /> 93 - {suffix !== null && ( 94 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 95 - )} 96 - {!isEmpty && ( 97 - <div {...stylex.props(inputStyles.addon, styles.clearButton)}> 98 - <IconButton 99 - label="Clear search" 100 - size="sm" 101 - variant="secondary" 102 - > 103 - <X /> 104 - </IconButton> 105 - </div> 106 - )} 107 - </div> 108 - {description && ( 109 - <Description size={size}>{description}</Description> 110 - )} 111 - <FieldError>{errorMessage}</FieldError> 112 - </> 113 - ); 114 - }} 115 - </AriaSearchField> 116 - ); 117 - }
-138
apps/example/src/components/select/index.tsx
··· 1 - import type { 2 - SelectProps as AriaSelectProps, 3 - PopoverProps, 4 - ValidationResult, 5 - } from "react-aria-components"; 6 - 7 - import * as stylex from "@stylexjs/stylex"; 8 - import { ChevronDown } from "lucide-react"; 9 - import { use } from "react"; 10 - import { 11 - Select as AriaSelect, 12 - Button, 13 - FieldError, 14 - Popover, 15 - SelectValue, 16 - } from "react-aria-components"; 17 - 18 - import type { Size } from "../types"; 19 - 20 - import { SizeContext } from "../context"; 21 - import { Description, Label } from "../label"; 22 - import { ListBox } from "../listbox"; 23 - import { useInputStyles } from "../theme/useInputStyles"; 24 - import { usePopoverStyles } from "../theme/usePopoverStyles"; 25 - 26 - const styles = stylex.create({ 27 - matchWidth: { 28 - width: "var(--trigger-width)", 29 - }, 30 - }); 31 - 32 - export interface SelectProps<T extends object, M extends "single" | "multiple"> 33 - extends 34 - Omit<AriaSelectProps<T, M>, "children" | "style" | "className">, 35 - Pick< 36 - PopoverProps, 37 - | "shouldCloseOnInteractOutside" 38 - | "shouldFlip" 39 - | "shouldUpdatePosition" 40 - | "placement" 41 - > { 42 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 43 - label?: string; 44 - description?: string; 45 - errorMessage?: string | ((validation: ValidationResult) => string); 46 - items?: Iterable<T>; 47 - children: React.ReactNode | ((item: T) => React.ReactNode); 48 - size?: Size; 49 - placeholder?: string; 50 - prefix?: React.ReactNode; 51 - suffix?: React.ReactNode; 52 - } 53 - 54 - export function Select< 55 - T extends object, 56 - M extends "single" | "multiple" = "single", 57 - >({ 58 - label, 59 - description, 60 - errorMessage, 61 - children, 62 - items, 63 - style, 64 - size: sizeProp, 65 - shouldCloseOnInteractOutside, 66 - shouldFlip, 67 - shouldUpdatePosition, 68 - placement, 69 - placeholder = "Select an option", 70 - prefix, 71 - suffix, 72 - ...props 73 - }: SelectProps<T, M>) { 74 - const size = sizeProp || use(SizeContext); 75 - const inputStyles = useInputStyles({ size }); 76 - const popoverStyles = usePopoverStyles(); 77 - 78 - return ( 79 - <SizeContext value={size}> 80 - <AriaSelect 81 - {...props} 82 - {...stylex.props(inputStyles.field, style)} 83 - placeholder={placeholder} 84 - > 85 - {label && <Label size={size}>{label}</Label>} 86 - <Button {...stylex.props(inputStyles.wrapper)}> 87 - {prefix !== null && ( 88 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 89 - )} 90 - <SelectValue {...stylex.props(inputStyles.input)}> 91 - {({ selectedText, isPlaceholder, defaultChildren }) => { 92 - if (isPlaceholder) return placeholder; 93 - if (selectedText) return selectedText; 94 - 95 - return defaultChildren; 96 - }} 97 - </SelectValue> 98 - {suffix !== null && ( 99 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 100 - )} 101 - <div {...stylex.props(inputStyles.addon)}> 102 - <ChevronDown size={16} aria-hidden="true" /> 103 - </div> 104 - </Button> 105 - {description && <Description size={size}>{description}</Description>} 106 - <FieldError>{errorMessage}</FieldError> 107 - <Popover 108 - containerPadding={8} 109 - shouldCloseOnInteractOutside={shouldCloseOnInteractOutside} 110 - shouldFlip={shouldFlip} 111 - shouldUpdatePosition={shouldUpdatePosition} 112 - placement={placement} 113 - > 114 - <ListBox 115 - items={items} 116 - {...stylex.props(popoverStyles, styles.matchWidth)} 117 - > 118 - {children} 119 - </ListBox> 120 - </Popover> 121 - </AriaSelect> 122 - </SizeContext> 123 - ); 124 - } 125 - 126 - export type { 127 - ListBoxItemProps as SelectItemProps, 128 - ListBoxSectionProps as SelectSectionProps, 129 - ListBoxSectionHeaderProps as SelectSectionHeaderProps, 130 - ListBoxSeparatorProps as SelectSeparatorProps, 131 - } from "../listbox"; 132 - 133 - export { 134 - ListBoxItem as SelectItem, 135 - ListBoxSection as SelectSection, 136 - ListBoxSectionHeader as SelectSectionHeader, 137 - ListBoxSeparator as SelectSeparator, 138 - } from "../listbox";
-35
apps/example/src/components/separator/index.tsx
··· 1 - import type { SeparatorProps as AriaSeparatorProps } from "react-aria-components"; 2 - 3 - import * as stylex from "@stylexjs/stylex"; 4 - import { Separator as AriaSeparator } from "react-aria-components"; 5 - 6 - import { slate } from "../theme/colors.stylex"; 7 - 8 - const styles = stylex.create({ 9 - separator: { 10 - margin: 0, 11 - borderWidth: 0, 12 - backgroundColor: slate.border2, 13 - height: { 14 - default: "1px", 15 - ":is([aria-orientation=vertical])": "100%", 16 - }, 17 - width: { 18 - default: "100%", 19 - ":is([aria-orientation=vertical])": "1px", 20 - }, 21 - }, 22 - }); 23 - 24 - export interface SeparatorProps extends Omit< 25 - AriaSeparatorProps, 26 - "style" | "className" 27 - > { 28 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 29 - } 30 - 31 - export function Separator({ style, ...props }: SeparatorProps) { 32 - return ( 33 - <AriaSeparator {...props} {...stylex.props(styles.separator, style)} /> 34 - ); 35 - }
-172
apps/example/src/components/text-area/index.tsx
··· 1 - import type { 2 - TextAreaProps as AriaTextAreaProps, 3 - InputProps, 4 - TextFieldProps, 5 - ValidationResult, 6 - } from "react-aria-components"; 7 - 8 - import * as stylex from "@stylexjs/stylex"; 9 - import { use, useRef } from "react"; 10 - import { 11 - TextArea as AriaTextArea, 12 - TextField as AriaTextField, 13 - FieldError, 14 - } from "react-aria-components"; 15 - 16 - import type { Size } from "../types"; 17 - 18 - import { SizeContext } from "../context"; 19 - import { Description, Label } from "../label"; 20 - import { slate } from "../theme/colors.stylex"; 21 - import { radius } from "../theme/radius.stylex"; 22 - import { gray } from "../theme/semantic-color.stylex"; 23 - import { spacing } from "../theme/spacing.stylex"; 24 - import { fontFamily, fontSize, lineHeight } from "../theme/typography.stylex"; 25 - 26 - const styles = stylex.create({ 27 - wrapper: { 28 - gap: spacing["2"], 29 - display: "flex", 30 - flexDirection: "column", 31 - }, 32 - addon: { 33 - color: gray.textDim, 34 - flexShrink: 0, 35 - height: "100%", 36 - minWidth: spacing["8"], 37 - paddingLeft: { ":first-child": spacing["0.5"] }, 38 - paddingRight: { 39 - ":last-child:has(svg)": spacing["0.5"], 40 - ":last-child": spacing["2"], 41 - }, 42 - 43 - gap: spacing["0.5"], 44 - alignItems: "center", 45 - display: "flex", 46 - justifyContent: "center", 47 - 48 - // eslint-disable-next-line @stylexjs/no-legacy-contextual-styles, @stylexjs/valid-styles 49 - ":is(*) svg": { 50 - flexShrink: 0, 51 - pointerEvents: "none", 52 - height: spacing["4"], 53 - width: spacing["4"], 54 - }, 55 - }, 56 - inputWrapper: { 57 - borderRadius: radius["md"], 58 - boxSizing: "border-box", 59 - display: "flex", 60 - 61 - borderColor: { 62 - default: slate.border2, 63 - ":hover": slate.border3, 64 - ":focus": slate.solid1, 65 - }, 66 - borderStyle: "solid", 67 - borderWidth: 1, 68 - }, 69 - input: { 70 - borderWidth: 0, 71 - outline: "none", 72 - backgroundColor: "transparent", 73 - boxSizing: "border-box", 74 - color: { 75 - "::placeholder": slate.text1, 76 - }, 77 - flexGrow: 1, 78 - fontFamily: fontFamily["sans"], 79 - }, 80 - smInput: { 81 - fontSize: fontSize["xs"], 82 - lineHeight: lineHeight["xs"], 83 - minHeight: spacing["6"], 84 - paddingBottom: spacing["1"], 85 - paddingLeft: { ":first-child": spacing["1"] }, 86 - paddingRight: spacing["1"], 87 - paddingTop: spacing["1"], 88 - }, 89 - mdInput: { 90 - fontSize: fontSize["sm"], 91 - lineHeight: lineHeight["sm"], 92 - minHeight: spacing["8"], 93 - paddingBottom: spacing["2"], 94 - paddingLeft: { ":first-child": spacing["2"] }, 95 - paddingRight: spacing["2"], 96 - paddingTop: spacing["2"], 97 - }, 98 - lgInput: { 99 - fontSize: fontSize["base"], 100 - lineHeight: lineHeight["base"], 101 - minHeight: spacing["10"], 102 - paddingBottom: spacing["3"], 103 - paddingLeft: spacing["3"], 104 - paddingRight: spacing["3"], 105 - paddingTop: spacing["3"], 106 - }, 107 - description: { 108 - color: gray.textDim, 109 - fontSize: fontSize["sm"], 110 - lineHeight: lineHeight["sm"], 111 - }, 112 - descriptionSm: { 113 - fontSize: fontSize["xs"], 114 - lineHeight: lineHeight["xs"], 115 - }, 116 - }); 117 - 118 - export interface TextAreaProps 119 - extends 120 - Omit<TextFieldProps, "style" | "className">, 121 - Pick<AriaTextAreaProps, "rows">, 122 - Pick<InputProps, "placeholder"> { 123 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 124 - label?: React.ReactNode; 125 - description?: string; 126 - errorMessage?: string | ((validation: ValidationResult) => string); 127 - size?: Size; 128 - prefix?: React.ReactNode; 129 - suffix?: React.ReactNode; 130 - } 131 - 132 - export function TextArea({ 133 - label, 134 - description, 135 - errorMessage, 136 - style, 137 - size: sizeProp, 138 - prefix, 139 - suffix, 140 - placeholder, 141 - rows, 142 - ...props 143 - }: TextAreaProps) { 144 - const textAreaRef = useRef<HTMLTextAreaElement>(null); 145 - const size = sizeProp || use(SizeContext); 146 - 147 - return ( 148 - <AriaTextField {...props} {...stylex.props(styles.wrapper, style)}> 149 - {label !== null && <Label size={size}>{label}</Label>} 150 - {/* 151 - This onClick is specifically for mouse users not clicking directly on the input. 152 - A keyboard user would not encounter the same issue. 153 - */} 154 - {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 155 - <div 156 - {...stylex.props(styles.inputWrapper, gray.bgUi, gray.text)} 157 - onClick={() => textAreaRef.current?.focus()} 158 - > 159 - {prefix !== null && <div {...stylex.props(styles.addon)}>{prefix}</div>} 160 - <AriaTextArea 161 - {...stylex.props(styles.input, styles[`${size}Input`])} 162 - ref={textAreaRef} 163 - placeholder={placeholder} 164 - rows={rows} 165 - /> 166 - {suffix !== null && <div {...stylex.props(styles.addon)}>{suffix}</div>} 167 - </div> 168 - {description && <Description size={size}>{description}</Description>} 169 - <FieldError>{errorMessage}</FieldError> 170 - </AriaTextField> 171 - ); 172 - }
-122
apps/example/src/components/text-field/index.tsx
··· 1 - import type { 2 - TextFieldProps as AriaTextFieldProps, 3 - InputProps, 4 - ValidationResult, 5 - } from "react-aria-components"; 6 - 7 - import * as stylex from "@stylexjs/stylex"; 8 - import { Eye, EyeOff } from "lucide-react"; 9 - import { use, useRef, useState } from "react"; 10 - import { 11 - TextField as AriaTextField, 12 - FieldError, 13 - Input, 14 - InputContext, 15 - } from "react-aria-components"; 16 - 17 - import type { Size } from "../types"; 18 - 19 - import { IconButton } from "../icon-button"; 20 - import { Description, Label } from "../label"; 21 - import { useInputStyles } from "../theme/useInputStyles"; 22 - 23 - function PasswordToggle({ 24 - type, 25 - setType, 26 - style, 27 - }: { 28 - type: TextFieldProps["type"]; 29 - setType: (type: TextFieldProps["type"]) => void; 30 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 31 - }) { 32 - const state = use(InputContext); 33 - 34 - if (!state || !("value" in state) || !state.value) return null; 35 - 36 - return ( 37 - <div {...stylex.props(style)}> 38 - <IconButton 39 - size="sm" 40 - variant="tertiary" 41 - label="Toggle password visibility" 42 - onPress={() => { 43 - setType(type === "password" ? "text" : "password"); 44 - }} 45 - > 46 - {type === "password" ? <EyeOff /> : <Eye />} 47 - </IconButton> 48 - </div> 49 - ); 50 - } 51 - 52 - export interface TextFieldProps 53 - extends 54 - Omit<AriaTextFieldProps, "style" | "className">, 55 - Pick<InputProps, "placeholder"> { 56 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 57 - label?: React.ReactNode; 58 - description?: string; 59 - errorMessage?: string | ((validation: ValidationResult) => string); 60 - size?: Size; 61 - prefix?: React.ReactNode; 62 - suffix?: React.ReactNode; 63 - } 64 - 65 - export function TextField({ 66 - label, 67 - description, 68 - errorMessage, 69 - style, 70 - size, 71 - prefix, 72 - suffix, 73 - placeholder, 74 - ...props 75 - }: TextFieldProps) { 76 - const inputRef = useRef<HTMLInputElement>(null); 77 - const [type, setType] = useState<TextFieldProps["type"]>( 78 - props.type || "text", 79 - ); 80 - const isPasswordInput = props.type === "password"; 81 - const inputStyles = useInputStyles({ size }); 82 - 83 - return ( 84 - <AriaTextField 85 - {...props} 86 - type={type} 87 - {...stylex.props(inputStyles.field, style)} 88 - > 89 - {label !== null && <Label size={size}>{label}</Label>} 90 - {/* 91 - This onClick is specifically for mouse users not clicking directly on the input. 92 - A keyboard user would not encounter the same issue. 93 - */} 94 - {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 95 - <div 96 - {...stylex.props(inputStyles.wrapper)} 97 - onClick={() => inputRef.current?.focus()} 98 - > 99 - {prefix !== null && ( 100 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 101 - )} 102 - <Input 103 - {...stylex.props(inputStyles.input)} 104 - ref={inputRef} 105 - placeholder={placeholder} 106 - /> 107 - {suffix !== null && ( 108 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 109 - )} 110 - {isPasswordInput && ( 111 - <PasswordToggle 112 - type={type} 113 - setType={setType} 114 - style={inputStyles.addon} 115 - /> 116 - )} 117 - </div> 118 - {description && <Description size={size}>{description}</Description>} 119 - <FieldError>{errorMessage}</FieldError> 120 - </AriaTextField> 121 - ); 122 - }
-24
apps/example/src/components/theme/animations.stylex.tsx
··· 1 - import * as stylex from "@stylexjs/stylex"; 2 - 3 - const fadeIn = stylex.keyframes({ 4 - from: { 5 - opacity: 0, 6 - }, 7 - to: { 8 - opacity: 1, 9 - }, 10 - }); 11 - 12 - const zoomIn = stylex.keyframes({ 13 - from: { 14 - transform: "scale(0.8)", 15 - }, 16 - to: { 17 - transform: "scale(1)", 18 - }, 19 - }); 20 - 21 - export const animations = stylex.defineVars({ 22 - fadeIn, 23 - zoomIn, 24 - });
-10
apps/example/src/components/theme/breakpoints.stylex.tsx
··· 1 - import * as stylex from "@stylexjs/stylex"; 2 - 3 - // eslint-disable-next-line @stylexjs/enforce-extension 4 - export const breakpoints = stylex.defineConsts({ 5 - sm: "@media (min-width: 40rem)", 6 - md: "@media (min-width: 48rem)", 7 - lg: "@media (min-width: 64rem)", 8 - xl: "@media (min-width: 80rem)", 9 - "2xl": "@media (min-width: 96rem)", 10 - });
-478
apps/example/src/components/theme/colors.stylex.tsx
··· 1 - import * as stylex from "@stylexjs/stylex"; 2 - 3 - export const slateLight = stylex.defineVars({ 4 - bg1: stylex.types.color("#fcfcfd"), 5 - bg2: stylex.types.color("#f9f9fb"), 6 - component1: stylex.types.color("#f0f0f3"), 7 - component2: stylex.types.color("#e8e8ec"), 8 - component3: stylex.types.color("#e0e1e6"), 9 - border1: stylex.types.color("#d9d9e0"), 10 - border2: stylex.types.color("#cdced6"), 11 - border3: stylex.types.color("#b9bbc6"), 12 - solid1: stylex.types.color("#8b8d98"), 13 - solid2: stylex.types.color("#80838d"), 14 - text1: stylex.types.color("#60646c"), 15 - text2: stylex.types.color("#1c2024"), 16 - }); 17 - 18 - export const slateLightP3 = stylex.defineVars({ 19 - bg1: stylex.types.color("color(display-p3 0.988 0.988 0.992)"), 20 - bg2: stylex.types.color("color(display-p3 0.976 0.976 0.984)"), 21 - component1: stylex.types.color("color(display-p3 0.94 0.941 0.953)"), 22 - component2: stylex.types.color("color(display-p3 0.908 0.909 0.925)"), 23 - component3: stylex.types.color("color(display-p3 0.88 0.881 0.901)"), 24 - border1: stylex.types.color("color(display-p3 0.85 0.852 0.876)"), 25 - border2: stylex.types.color("color(display-p3 0.805 0.808 0.838)"), 26 - border3: stylex.types.color("color(display-p3 0.727 0.733 0.773)"), 27 - solid1: stylex.types.color("color(display-p3 0.547 0.553 0.592)"), 28 - solid2: stylex.types.color("color(display-p3 0.503 0.512 0.549)"), 29 - text1: stylex.types.color("color(display-p3 0.379 0.392 0.421)"), 30 - text2: stylex.types.color("color(display-p3 0.113 0.125 0.14)"), 31 - }); 32 - 33 - export const slateDark = stylex.defineVars({ 34 - bg1: stylex.types.color("#111113"), 35 - bg2: stylex.types.color("#18191b"), 36 - component1: stylex.types.color("#212225"), 37 - component2: stylex.types.color("#272a2d"), 38 - component3: stylex.types.color("#2e3135"), 39 - border1: stylex.types.color("#363a3f"), 40 - border2: stylex.types.color("#43484e"), 41 - border3: stylex.types.color("#5a6169"), 42 - solid1: stylex.types.color("#696e77"), 43 - solid2: stylex.types.color("#777b84"), 44 - text1: stylex.types.color("#b0b4ba"), 45 - text2: stylex.types.color("#edeef0"), 46 - }); 47 - 48 - export const slateDarkP3 = stylex.defineVars({ 49 - bg1: stylex.types.color("color(display-p3 0.067 0.067 0.074)"), 50 - bg2: stylex.types.color("color(display-p3 0.095 0.098 0.105)"), 51 - component1: stylex.types.color("color(display-p3 0.13 0.135 0.145)"), 52 - component2: stylex.types.color("color(display-p3 0.156 0.163 0.176)"), 53 - component3: stylex.types.color("color(display-p3 0.183 0.191 0.206)"), 54 - border1: stylex.types.color("color(display-p3 0.215 0.226 0.244)"), 55 - border2: stylex.types.color("color(display-p3 0.265 0.28 0.302)"), 56 - border3: stylex.types.color("color(display-p3 0.357 0.381 0.409)"), 57 - solid1: stylex.types.color("color(display-p3 0.415 0.431 0.463)"), 58 - solid2: stylex.types.color("color(display-p3 0.469 0.483 0.514)"), 59 - text1: stylex.types.color("color(display-p3 0.692 0.704 0.728)"), 60 - text2: stylex.types.color("color(display-p3 0.93 0.933 0.94)"), 61 - }); 62 - 63 - export const slate = stylex.defineVars({ 64 - bg1: { 65 - default: `light-dark(${slateLight.bg1}, ${slateDark.bg1})`, 66 - "@media (color-gamut: p3)": `light-dark(${slateLightP3.bg1}, ${slateDarkP3.bg1})`, 67 - }, 68 - bg2: { 69 - default: `light-dark(${slateLight.bg2}, ${slateDark.bg2})`, 70 - "@media (color-gamut: p3)": `light-dark(${slateLightP3.bg2}, ${slateDarkP3.bg2})`, 71 - }, 72 - component1: { 73 - default: `light-dark(${slateLight.component1}, ${slateDark.component1})`, 74 - "@media (color-gamut: p3)": `light-dark(${slateLightP3.component1}, ${slateDarkP3.component1})`, 75 - }, 76 - component2: { 77 - default: `light-dark(${slateLight.component2}, ${slateDark.component2})`, 78 - "@media (color-gamut: p3)": `light-dark(${slateLightP3.component2}, ${slateDarkP3.component2})`, 79 - }, 80 - component3: { 81 - default: `light-dark(${slateLight.component3}, ${slateDark.component3})`, 82 - "@media (color-gamut: p3)": `light-dark(${slateLightP3.component3}, ${slateDarkP3.component3})`, 83 - }, 84 - border1: { 85 - default: `light-dark(${slateLight.border1}, ${slateDark.border1})`, 86 - "@media (color-gamut: p3)": `light-dark(${slateLightP3.border1}, ${slateDarkP3.border1})`, 87 - }, 88 - border2: { 89 - default: `light-dark(${slateLight.border2}, ${slateDark.border2})`, 90 - "@media (color-gamut: p3)": `light-dark(${slateLightP3.border2}, ${slateDarkP3.border2})`, 91 - }, 92 - border3: { 93 - default: `light-dark(${slateLight.border3}, ${slateDark.border3})`, 94 - "@media (color-gamut: p3)": `light-dark(${slateLightP3.border3}, ${slateDarkP3.border3})`, 95 - }, 96 - solid1: { 97 - default: `light-dark(${slateLight.solid1}, ${slateDark.solid1})`, 98 - "@media (color-gamut: p3)": `light-dark(${slateLightP3.solid1}, ${slateDarkP3.solid1})`, 99 - }, 100 - solid2: { 101 - default: `light-dark(${slateLight.solid2}, ${slateDark.solid2})`, 102 - "@media (color-gamut: p3)": `light-dark(${slateLightP3.solid2}, ${slateDarkP3.solid2})`, 103 - }, 104 - text1: { 105 - default: `light-dark(${slateLight.text1}, ${slateDark.text1})`, 106 - "@media (color-gamut: p3)": `light-dark(${slateLightP3.text1}, ${slateDarkP3.text1})`, 107 - }, 108 - text2: { 109 - default: `light-dark(${slateLight.text2}, ${slateDark.text2})`, 110 - "@media (color-gamut: p3)": `light-dark(${slateLightP3.text2}, ${slateDarkP3.text2})`, 111 - }, 112 - }); 113 - 114 - export const slateInverted = stylex.defineVars({ 115 - bg1: { 116 - default: `light-dark(${slateDark.bg1}, ${slateLight.bg1})`, 117 - "@media (color-gamut: p3)": `light-dark(${slateDarkP3.bg1}, ${slateLightP3.bg1})`, 118 - }, 119 - bg2: { 120 - default: `light-dark(${slateDark.bg2}, ${slateLight.bg2})`, 121 - "@media (color-gamut: p3)": `light-dark(${slateDarkP3.bg2}, ${slateLightP3.bg2})`, 122 - }, 123 - component1: { 124 - default: `light-dark(${slateDark.component1}, ${slateLight["component1"]})`, 125 - "@media (color-gamut: p3)": `light-dark(${slateDarkP3.component1}, ${slateLightP3.component1})`, 126 - }, 127 - component2: { 128 - default: `light-dark(${slateDark.component2}, ${slateLight["component2"]})`, 129 - "@media (color-gamut: p3)": `light-dark(${slateDarkP3.component2}, ${slateLightP3.component2})`, 130 - }, 131 - component3: { 132 - default: `light-dark(${slateDark.component3}, ${slateLight["component3"]})`, 133 - "@media (color-gamut: p3)": `light-dark(${slateDarkP3.component3}, ${slateLightP3.component3})`, 134 - }, 135 - border1: { 136 - default: `light-dark(${slateDark.border1}, ${slateLight.border1})`, 137 - "@media (color-gamut: p3)": `light-dark(${slateDarkP3.border1}, ${slateLightP3.border1})`, 138 - }, 139 - border2: { 140 - default: `light-dark(${slateDark.border2}, ${slateLight.border2})`, 141 - "@media (color-gamut: p3)": `light-dark(${slateDarkP3.border2}, ${slateLightP3.border2})`, 142 - }, 143 - border3: { 144 - default: `light-dark(${slateDark.border3}, ${slateLight.border3})`, 145 - "@media (color-gamut: p3)": `light-dark(${slateDarkP3.border3}, ${slateLightP3.border3})`, 146 - }, 147 - solid1: { 148 - default: `light-dark(${slateDark.solid1}, ${slateLight.solid1})`, 149 - "@media (color-gamut: p3)": `light-dark(${slateDarkP3.solid1}, ${slateLightP3.solid1})`, 150 - }, 151 - solid2: { 152 - default: `light-dark(${slateDark.solid2}, ${slateLight.solid2})`, 153 - "@media (color-gamut: p3)": `light-dark(${slateDarkP3.solid2}, ${slateLightP3.solid2})`, 154 - }, 155 - text1: { 156 - default: `light-dark(${slateDark.text1}, ${slateLight.text1})`, 157 - "@media (color-gamut: p3)": `light-dark(${slateDarkP3.text1}, ${slateLightP3.text1})`, 158 - }, 159 - text2: { 160 - default: `light-dark(${slateDark.text2}, ${slateLight.text2})`, 161 - "@media (color-gamut: p3)": `light-dark(${slateDarkP3.text2}, ${slateLightP3.text2})`, 162 - }, 163 - }); 164 - 165 - export const plum = stylex.defineVars({ 166 - bg1: { 167 - default: "light-dark(#fefcff, #181118)", 168 - "@media (color-gamut: p3)": 169 - "light-dark(color(display-p3 0.995 0.988 0.999), color(display-p3 0.09 0.068 0.092))", 170 - }, 171 - bg2: { 172 - default: "light-dark(#fdf7fd, #201320)", 173 - "@media (color-gamut: p3)": 174 - "light-dark(color(display-p3 0.988 0.971 0.99), color(display-p3 0.118 0.077 0.121))", 175 - }, 176 - component1: { 177 - default: "light-dark(#fbebfb, #351a35)", 178 - "@media (color-gamut: p3)": 179 - "light-dark(color(display-p3 0.973 0.923 0.98), color(display-p3 0.192 0.105 0.202))", 180 - }, 181 - component2: { 182 - default: "light-dark(#f7def8, #451d47)", 183 - "@media (color-gamut: p3)": 184 - "light-dark(color(display-p3 0.953 0.875 0.966), color(display-p3 0.25 0.121 0.271))", 185 - }, 186 - component3: { 187 - default: "light-dark(#f2d1f3, #512454)", 188 - "@media (color-gamut: p3)": 189 - "light-dark(color(display-p3 0.926 0.825 0.945), color(display-p3 0.293 0.152 0.319))", 190 - }, 191 - border1: { 192 - default: "light-dark(#e9c2ec, #5e3061)", 193 - "@media (color-gamut: p3)": 194 - "light-dark(color(display-p3 0.89 0.765 0.916), color(display-p3 0.343 0.198 0.372))", 195 - }, 196 - border2: { 197 - default: "light-dark(#deade3, #734079)", 198 - "@media (color-gamut: p3)": 199 - "light-dark(color(display-p3 0.84 0.686 0.877), color(display-p3 0.424 0.262 0.461))", 200 - }, 201 - border3: { 202 - default: "light-dark(#cf91d8, #92549c)", 203 - "@media (color-gamut: p3)": 204 - "light-dark(color(display-p3 0.775 0.58 0.832), color(display-p3 0.54 0.341 0.595))", 205 - }, 206 - solid1: { 207 - default: "light-dark(#ab4aba, #ab4aba)", 208 - "@media (color-gamut: p3)": 209 - "light-dark(color(display-p3 0.624 0.313 0.708), color(display-p3 0.624 0.313 0.708))", 210 - }, 211 - solid2: { 212 - default: "light-dark(#a144af, #b658c4)", 213 - "@media (color-gamut: p3)": 214 - "light-dark(color(display-p3 0.587 0.29 0.667), color(display-p3 0.666 0.365 0.748))", 215 - }, 216 - text1: { 217 - default: "light-dark(#953ea3, #e796f3)", 218 - "@media (color-gamut: p3)": 219 - "light-dark(color(display-p3 0.543 0.263 0.619), color(display-p3 0.86 0.602 0.933))", 220 - }, 221 - text2: { 222 - default: "light-dark(#53195d, #f4d4f4)", 223 - "@media (color-gamut: p3)": 224 - "light-dark(color(display-p3 0.299 0.114 0.352), color(display-p3 0.936 0.836 0.949))", 225 - }, 226 - }); 227 - 228 - export const blue = stylex.defineVars({ 229 - bg1: { 230 - default: "light-dark(#fbfdff, #0d1520)", 231 - "@media (color-gamut: p3)": 232 - "light-dark(color(display-p3 0.986 0.992 0.999), color(display-p3 0.057 0.081 0.122))", 233 - }, 234 - bg2: { 235 - default: "light-dark(#f4faff, #111927)", 236 - "@media (color-gamut: p3)": 237 - "light-dark(color(display-p3 0.96 0.979 0.998), color(display-p3 0.072 0.098 0.147))", 238 - }, 239 - component1: { 240 - default: "light-dark(#e6f4fe, #0d2847)", 241 - "@media (color-gamut: p3)": 242 - "light-dark(color(display-p3 0.912 0.956 0.991), color(display-p3 0.078 0.154 0.27))", 243 - }, 244 - component2: { 245 - default: "light-dark(#d5efff, #003362)", 246 - "@media (color-gamut: p3)": 247 - "light-dark(color(display-p3 0.853 0.932 1), color(display-p3 0.033 0.197 0.37))", 248 - }, 249 - component3: { 250 - default: "light-dark(#c2e5ff, #004074)", 251 - "@media (color-gamut: p3)": 252 - "light-dark(color(display-p3 0.788 0.894 0.998), color(display-p3 0.08 0.245 0.441))", 253 - }, 254 - border1: { 255 - default: "light-dark(#acd8fc, #104d87)", 256 - "@media (color-gamut: p3)": 257 - "light-dark(color(display-p3 0.709 0.843 0.976), color(display-p3 0.14 0.298 0.511))", 258 - }, 259 - border2: { 260 - default: "light-dark(#8ec8f6, #205d9e)", 261 - "@media (color-gamut: p3)": 262 - "light-dark(color(display-p3 0.606 0.777 0.947), color(display-p3 0.195 0.361 0.6))", 263 - }, 264 - border3: { 265 - default: "light-dark(#5eb1ef, #2870bd)", 266 - "@media (color-gamut: p3)": 267 - "light-dark(color(display-p3 0.451 0.688 0.917), color(display-p3 0.239 0.434 0.72))", 268 - }, 269 - solid1: { 270 - default: "light-dark(#0090ff, #0090ff)", 271 - "@media (color-gamut: p3)": 272 - "light-dark(color(display-p3 0.247 0.556 0.969), color(display-p3 0.247 0.556 0.969))", 273 - }, 274 - solid2: { 275 - default: "light-dark(#0588f0, #3b9eff)", 276 - "@media (color-gamut: p3)": 277 - "light-dark(color(display-p3 0.234 0.523 0.912), color(display-p3 0.344 0.612 0.973))", 278 - }, 279 - text1: { 280 - default: "light-dark(#0d74ce, #70b8ff)", 281 - "@media (color-gamut: p3)": 282 - "light-dark(color(display-p3 0.15 0.44 0.84), color(display-p3 0.49 0.72 1))", 283 - }, 284 - text2: { 285 - default: "light-dark(#113264, #c2e6ff)", 286 - "@media (color-gamut: p3)": 287 - "light-dark(color(display-p3 0.102 0.193 0.379), color(display-p3 0.788 0.898 0.99))", 288 - }, 289 - }); 290 - 291 - export const red = stylex.defineVars({ 292 - bg1: { 293 - default: "light-dark(#fffcfc, #191111)", 294 - "@media (color-gamut: p3)": 295 - "light-dark(color(display-p3 0.998 0.989 0.988), color(display-p3 0.093 0.068 0.067))", 296 - }, 297 - bg2: { 298 - default: "light-dark(#fff7f7, #201314)", 299 - "@media (color-gamut: p3)": 300 - "light-dark(color(display-p3 0.995 0.971 0.971), color(display-p3 0.118 0.077 0.079))", 301 - }, 302 - component1: { 303 - default: "light-dark(#feebec, #3b1219)", 304 - "@media (color-gamut: p3)": 305 - "light-dark(color(display-p3 0.985 0.925 0.925), color(display-p3 0.211 0.081 0.099))", 306 - }, 307 - component2: { 308 - default: "light-dark(#ffdbdc, #500f1c)", 309 - "@media (color-gamut: p3)": 310 - "light-dark(color(display-p3 0.999 0.866 0.866), color(display-p3 0.287 0.079 0.113))", 311 - }, 312 - component3: { 313 - default: "light-dark(#ffcdce, #611623)", 314 - "@media (color-gamut: p3)": 315 - "light-dark(color(display-p3 0.984 0.812 0.811), color(display-p3 0.348 0.11 0.142))", 316 - }, 317 - border1: { 318 - default: "light-dark(#fdbdbe, #72232d)", 319 - "@media (color-gamut: p3)": 320 - "light-dark(color(display-p3 0.955 0.751 0.749), color(display-p3 0.414 0.16 0.183))", 321 - }, 322 - border2: { 323 - default: "light-dark(#f4a9aa, #8c333a)", 324 - "@media (color-gamut: p3)": 325 - "light-dark(color(display-p3 0.915 0.675 0.672), color(display-p3 0.508 0.224 0.236))", 326 - }, 327 - border3: { 328 - default: "light-dark(#eb8e90, #b54548)", 329 - "@media (color-gamut: p3)": 330 - "light-dark(color(display-p3 0.872 0.575 0.572), color(display-p3 0.659 0.298 0.297))", 331 - }, 332 - solid1: { 333 - default: "light-dark(#e5484d, #e5484d)", 334 - "@media (color-gamut: p3)": 335 - "light-dark(color(display-p3 0.83 0.329 0.324), color(display-p3 0.83 0.329 0.324))", 336 - }, 337 - solid2: { 338 - default: "light-dark(#dc3e42, #ec5d5e)", 339 - "@media (color-gamut: p3)": 340 - "light-dark(color(display-p3 0.798 0.294 0.285), color(display-p3 0.861 0.403 0.387))", 341 - }, 342 - text1: { 343 - default: "light-dark(#ce2c31, #ff9592)", 344 - "@media (color-gamut: p3)": 345 - "light-dark(color(display-p3 0.744 0.234 0.222), color(display-p3 1 0.57 0.55))", 346 - }, 347 - text2: { 348 - default: "light-dark(#641723, #ffd1d9)", 349 - "@media (color-gamut: p3)": 350 - "light-dark(color(display-p3 0.36 0.115 0.143), color(display-p3 0.971 0.826 0.852))", 351 - }, 352 - }); 353 - 354 - export const yellow = stylex.defineVars({ 355 - bg1: { 356 - default: "light-dark(#fdfdf9, #14120b)", 357 - "@media (color-gamut: p3)": 358 - "light-dark(color(display-p3 0.992 0.992 0.978), color(display-p3 0.078 0.069 0.047))", 359 - }, 360 - bg2: { 361 - default: "light-dark(#fefce9, #1b180f)", 362 - "@media (color-gamut: p3)": 363 - "light-dark(color(display-p3 0.995 0.99 0.922), color(display-p3 0.103 0.094 0.063))", 364 - }, 365 - component1: { 366 - default: "light-dark(#fffab8, #2d2305)", 367 - "@media (color-gamut: p3)": 368 - "light-dark(color(display-p3 0.997 0.982 0.749), color(display-p3 0.168 0.137 0.039))", 369 - }, 370 - component2: { 371 - default: "light-dark(#fff394, #362b00)", 372 - "@media (color-gamut: p3)": 373 - "light-dark(color(display-p3 0.992 0.953 0.627), color(display-p3 0.209 0.169 0))", 374 - }, 375 - component3: { 376 - default: "light-dark(#ffe770, #433500)", 377 - "@media (color-gamut: p3)": 378 - "light-dark(color(display-p3 0.984 0.91 0.51), color(display-p3 0.255 0.209 0))", 379 - }, 380 - border1: { 381 - default: "light-dark(#f3d768, #524202)", 382 - "@media (color-gamut: p3)": 383 - "light-dark(color(display-p3 0.934 0.847 0.474), color(display-p3 0.31 0.261 0.07))", 384 - }, 385 - border2: { 386 - default: "light-dark(#e4c767, #665417)", 387 - "@media (color-gamut: p3)": 388 - "light-dark(color(display-p3 0.876 0.785 0.46), color(display-p3 0.389 0.331 0.135))", 389 - }, 390 - border3: { 391 - default: "light-dark(#d5ae39, #836a21)", 392 - "@media (color-gamut: p3)": 393 - "light-dark(color(display-p3 0.811 0.689 0.313), color(display-p3 0.497 0.42 0.182))", 394 - }, 395 - solid1: { 396 - default: "light-dark(#ffe629, #ffe629)", 397 - "@media (color-gamut: p3)": 398 - "light-dark(color(display-p3 1 0.92 0.22), color(display-p3 1 0.92 0.22))", 399 - }, 400 - solid2: { 401 - default: "light-dark(#ffdc00, #ffff57)", 402 - "@media (color-gamut: p3)": 403 - "light-dark(color(display-p3 0.977 0.868 0.291), color(display-p3 1 1 0.456))", 404 - }, 405 - text1: { 406 - default: "light-dark(#9e6c00, #f5e147)", 407 - "@media (color-gamut: p3)": 408 - "light-dark(color(display-p3 0.6 0.44 0), color(display-p3 0.948 0.885 0.392))", 409 - }, 410 - text2: { 411 - default: "light-dark(#473b1f, #f6eeb4)", 412 - "@media (color-gamut: p3)": 413 - "light-dark(color(display-p3 0.271 0.233 0.137), color(display-p3 0.959 0.934 0.731))", 414 - }, 415 - }); 416 - 417 - export const green = stylex.defineVars({ 418 - bg1: { 419 - default: "light-dark(#fbfefc, #0e1512)", 420 - "@media (color-gamut: p3)": 421 - "light-dark(color(display-p3 0.986 0.996 0.989), color(display-p3 0.062 0.083 0.071))", 422 - }, 423 - bg2: { 424 - default: "light-dark(#f4fbf6, #121b17)", 425 - "@media (color-gamut: p3)": 426 - "light-dark(color(display-p3 0.963 0.983 0.967), color(display-p3 0.079 0.106 0.09))", 427 - }, 428 - component1: { 429 - default: "light-dark(#e6f6eb, #132d21)", 430 - "@media (color-gamut: p3)": 431 - "light-dark(color(display-p3 0.913 0.964 0.925), color(display-p3 0.1 0.173 0.133))", 432 - }, 433 - component2: { 434 - default: "light-dark(#d6f1df, #113b29)", 435 - "@media (color-gamut: p3)": 436 - "light-dark(color(display-p3 0.859 0.94 0.879), color(display-p3 0.115 0.229 0.166))", 437 - }, 438 - component3: { 439 - default: "light-dark(#c4e8d1, #174933)", 440 - "@media (color-gamut: p3)": 441 - "light-dark(color(display-p3 0.796 0.907 0.826), color(display-p3 0.147 0.282 0.206))", 442 - }, 443 - border1: { 444 - default: "light-dark(#adddc0, #19573a)", 445 - "@media (color-gamut: p3)": 446 - "light-dark(color(display-p3 0.718 0.863 0.761), color(display-p3 0.185 0.338 0.25))", 447 - }, 448 - border2: { 449 - default: "light-dark(#8eceaa, #28684a)", 450 - "@media (color-gamut: p3)": 451 - "light-dark(color(display-p3 0.61 0.801 0.675), color(display-p3 0.227 0.403 0.298))", 452 - }, 453 - border3: { 454 - default: "light-dark(#5bb98b, #2f7c57)", 455 - "@media (color-gamut: p3)": 456 - "light-dark(color(display-p3 0.451 0.715 0.559), color(display-p3 0.27 0.479 0.351))", 457 - }, 458 - solid1: { 459 - default: "light-dark(#30a46c, #30a46c)", 460 - "@media (color-gamut: p3)": 461 - "light-dark(color(display-p3 0.332 0.634 0.442), color(display-p3 0.332 0.634 0.442))", 462 - }, 463 - solid2: { 464 - default: "light-dark(#2b9a66, #33b074)", 465 - "@media (color-gamut: p3)": 466 - "light-dark(color(display-p3 0.308 0.595 0.417), color(display-p3 0.357 0.682 0.474))", 467 - }, 468 - text1: { 469 - default: "light-dark(#218358, #3dd68c)", 470 - "@media (color-gamut: p3)": 471 - "light-dark(color(display-p3 0.19 0.5 0.32), color(display-p3 0.434 0.828 0.573))", 472 - }, 473 - text2: { 474 - default: "light-dark(#193b2d, #b1f1cb)", 475 - "@media (color-gamut: p3)": 476 - "light-dark(color(display-p3 0.132 0.228 0.18), color(display-p3 0.747 0.938 0.807))", 477 - }, 478 - });
-13
apps/example/src/components/theme/radius.stylex.tsx
··· 1 - import * as stylex from "@stylexjs/stylex"; 2 - 3 - export const radius = stylex.defineVars({ 4 - xs: "0.125rem", 5 - sm: "0.25rem", 6 - md: "0.375rem", 7 - lg: "0.5rem", 8 - xl: "0.75rem", 9 - "2xl": "1rem", 10 - "3xl": "1.5rem", 11 - "4xl": "2rem", 12 - full: "calc(infinity * 1px)", 13 - });
-377
apps/example/src/components/theme/semantic-color.stylex.tsx
··· 1 - import * as stylex from "@stylexjs/stylex"; 2 - 3 - import { animationDuration } from "./animations.stylex"; 4 - import { green, plum, red, slate, yellow } from "./colors.stylex"; 5 - import { fontFamily } from "./typography.stylex"; 6 - 7 - // eslint-disable-next-line @stylexjs/enforce-extension 8 - export const gray = stylex.create({ 9 - bg: { backgroundColor: slate.bg1 }, 10 - bgSubtle: { backgroundColor: slate.bg2 }, 11 - bgDim: { backgroundColor: slate.component1 }, 12 - bgSecondary: { backgroundColor: slate.component2 }, 13 - bgActive: { backgroundColor: slate.component3 }, 14 - borderDim: { 15 - borderColor: slate.border1, 16 - borderStyle: "solid", 17 - borderWidth: 1, 18 - }, 19 - border: { 20 - borderColor: slate.border2, 21 - borderStyle: "solid", 22 - borderWidth: 1, 23 - }, 24 - borderInteractive: { 25 - borderColor: { 26 - default: slate.border2, 27 - ":hover": slate.border3, 28 - }, 29 - borderStyle: "solid", 30 - borderWidth: 1, 31 - 32 - transitionDuration: animationDuration.fast, 33 - transitionProperty: "background-color, border-color", 34 - transitionTimingFunction: "ease-in-out", 35 - }, 36 - bgSolid: { backgroundColor: slate.solid1 }, 37 - bgSolidDark: { backgroundColor: slate.solid2 }, 38 - textDim: { color: slate.text1, fontFamily: fontFamily["sans"] }, 39 - text: { color: slate.text2, fontFamily: fontFamily["sans"] }, 40 - textContrast: { color: "white" }, 41 - 42 - bgGhost: { 43 - backgroundColor: { 44 - default: "transparent", 45 - ":active:not(:disabled)": slate.component3, 46 - ":hover:not(:has(* button:hover)):not(:disabled)": slate.component2, 47 - ":disabled": slate.component1, 48 - }, 49 - transitionDuration: animationDuration.fast, 50 - transitionProperty: "background-color, border-color", 51 - transitionTimingFunction: "ease-in-out", 52 - }, 53 - bgUi: { 54 - backgroundColor: { 55 - default: slate.component1, 56 - ":active:not(:disabled)": slate.component3, 57 - ":hover:not(:has(* button:hover)):not(:disabled)": slate.component2, 58 - ":disabled": slate.component1, 59 - }, 60 - transitionDuration: animationDuration.fast, 61 - transitionProperty: "background-color, border-color", 62 - transitionTimingFunction: "ease-in-out", 63 - }, 64 - bgAction: { 65 - backgroundColor: { 66 - default: slate.component2, 67 - ":active:not(:disabled)": slate.component3, 68 - ":hover:not(:has(* button:hover)):not(:disabled)": slate.component3, 69 - ":disabled": slate.component1, 70 - }, 71 - transitionDuration: animationDuration.fast, 72 - transitionProperty: "background-color, border-color", 73 - transitionTimingFunction: "ease-in-out", 74 - }, 75 - }); 76 - 77 - // eslint-disable-next-line @stylexjs/enforce-extension 78 - export const primary = stylex.create({ 79 - bg: { backgroundColor: plum.bg1 }, 80 - bgSubtle: { backgroundColor: plum.bg2 }, 81 - bgDim: { backgroundColor: plum.component1 }, 82 - bgSecondary: { backgroundColor: plum.component2 }, 83 - bgActive: { backgroundColor: plum.component3 }, 84 - borderDim: { 85 - borderColor: plum.border1, 86 - borderStyle: "solid", 87 - borderWidth: 1, 88 - }, 89 - border: { 90 - borderColor: plum.border2, 91 - borderStyle: "solid", 92 - borderWidth: 1, 93 - }, 94 - borderInteractive: { 95 - borderColor: { 96 - default: plum.border2, 97 - ":hover": plum.border3, 98 - }, 99 - borderStyle: "solid", 100 - borderWidth: 1, 101 - 102 - transitionDuration: animationDuration.fast, 103 - transitionProperty: "background-color, border-color", 104 - transitionTimingFunction: "ease-in-out", 105 - }, 106 - bgSolid: { backgroundColor: plum.solid1 }, 107 - bgSolidDark: { backgroundColor: plum.solid2 }, 108 - textDim: { color: plum.text1, fontFamily: fontFamily["sans"] }, 109 - text: { color: plum.text2, fontFamily: fontFamily["sans"] }, 110 - textContrast: { color: "white" }, 111 - 112 - bgGhost: { 113 - backgroundColor: { 114 - default: "transparent", 115 - ":active:not(:disabled)": plum.component3, 116 - ":hover:not(:has(* button:hover)):not(:disabled)": plum.component2, 117 - ":disabled": plum.component1, 118 - }, 119 - transitionDuration: animationDuration.fast, 120 - transitionProperty: "background-color, border-color", 121 - transitionTimingFunction: "ease-in-out", 122 - }, 123 - bgUi: { 124 - backgroundColor: { 125 - default: plum.component1, 126 - ":hover:not(:has(* button:hover)):not(:disabled)": plum.component2, 127 - ":disabled": plum.component1, 128 - ":active": plum.component3, 129 - }, 130 - transitionDuration: animationDuration.fast, 131 - transitionProperty: "background-color, border-color", 132 - transitionTimingFunction: "ease-in-out", 133 - }, 134 - bgAction: { 135 - backgroundColor: { 136 - default: plum.component2, 137 - ":active:not(:disabled)": plum.component3, 138 - ":hover:not(:has(* button:hover)):not(:disabled)": plum.component3, 139 - ":disabled": plum.component1, 140 - }, 141 - transitionDuration: animationDuration.fast, 142 - transitionProperty: "background-color, border-color", 143 - transitionTimingFunction: "ease-in-out", 144 - }, 145 - }); 146 - 147 - // eslint-disable-next-line @stylexjs/enforce-extension 148 - export const critical = stylex.create({ 149 - bg: { backgroundColor: red.bg1 }, 150 - bgSubtle: { backgroundColor: red.bg2 }, 151 - bgDim: { backgroundColor: red.component1 }, 152 - bgSecondary: { backgroundColor: red.component2 }, 153 - bgActive: { backgroundColor: red.component3 }, 154 - borderDim: { 155 - borderColor: red.border1, 156 - borderStyle: "solid", 157 - borderWidth: 1, 158 - }, 159 - border: { 160 - borderColor: red.border2, 161 - borderStyle: "solid", 162 - borderWidth: 1, 163 - }, 164 - borderInteractive: { 165 - borderColor: { 166 - default: red.border2, 167 - ":hover": red.border3, 168 - }, 169 - borderStyle: "solid", 170 - borderWidth: 1, 171 - transitionDuration: animationDuration.fast, 172 - transitionProperty: "background-color, border-color", 173 - transitionTimingFunction: "ease-in-out", 174 - }, 175 - bgSolid: { backgroundColor: red.solid1 }, 176 - bgSolidDark: { backgroundColor: red.solid2 }, 177 - textDim: { color: red.text1, fontFamily: fontFamily["sans"] }, 178 - text: { color: red.text2, fontFamily: fontFamily["sans"] }, 179 - textContrast: { color: "white" }, 180 - 181 - bgGhost: { 182 - backgroundColor: { 183 - default: "transparent", 184 - ":active:not(:disabled)": red.component3, 185 - ":hover:not(:has(* button:hover)):not(:disabled)": red.component2, 186 - ":disabled": red.component1, 187 - }, 188 - transitionDuration: animationDuration.fast, 189 - transitionProperty: "background-color, border-color", 190 - transitionTimingFunction: "ease-in-out", 191 - }, 192 - bgUi: { 193 - backgroundColor: { 194 - default: red.component1, 195 - ":active:not(:disabled)": red.component3, 196 - ":hover:not(:has(* button:hover)):not(:disabled)": red.component2, 197 - ":disabled": red.component1, 198 - }, 199 - transitionDuration: animationDuration.fast, 200 - transitionProperty: "background-color, border-color", 201 - transitionTimingFunction: "ease-in-out", 202 - }, 203 - bgAction: { 204 - backgroundColor: { 205 - default: red.component2, 206 - ":active:not(:disabled)": red.component3, 207 - ":hover:not(:has(* button:hover)):not(:disabled)": red.component3, 208 - ":disabled": red.component1, 209 - }, 210 - transitionDuration: animationDuration.fast, 211 - transitionProperty: "background-color, border-color", 212 - transitionTimingFunction: "ease-in-out", 213 - }, 214 - bgSolidAction: { 215 - backgroundColor: { 216 - default: red.solid1, 217 - ":hover:not(:has(* button:hover)):not(:disabled)": red.solid2, 218 - ":disabled": red.component1, 219 - }, 220 - transitionDuration: animationDuration.fast, 221 - transitionProperty: "background-color, border-color", 222 - transitionTimingFunction: "ease-in-out", 223 - }, 224 - }); 225 - 226 - // eslint-disable-next-line @stylexjs/enforce-extension 227 - export const warning = stylex.create({ 228 - bg: { backgroundColor: yellow.bg1 }, 229 - bgSubtle: { backgroundColor: yellow.bg2 }, 230 - bgDim: { backgroundColor: yellow.component1 }, 231 - bgSecondary: { backgroundColor: yellow.component2 }, 232 - bgActive: { backgroundColor: yellow.component3 }, 233 - borderDim: { 234 - borderColor: yellow.border1, 235 - borderStyle: "solid", 236 - borderWidth: 1, 237 - }, 238 - border: { 239 - borderColor: yellow.border2, 240 - borderStyle: "solid", 241 - borderWidth: 1, 242 - }, 243 - borderInteractive: { 244 - borderColor: { 245 - default: yellow.border2, 246 - ":hover": yellow.border3, 247 - }, 248 - }, 249 - bgSolid: { backgroundColor: yellow.solid1 }, 250 - bgSolidDark: { backgroundColor: yellow.solid2 }, 251 - textDim: { color: yellow.text1, fontFamily: fontFamily["sans"] }, 252 - text: { color: yellow.text2, fontFamily: fontFamily["sans"] }, 253 - textContrast: { color: "black" }, 254 - 255 - bgGhost: { 256 - backgroundColor: { 257 - default: "transparent", 258 - ":active:not(:disabled)": yellow.component3, 259 - ":hover:not(:has(* button:hover)):not(:disabled)": yellow.component2, 260 - ":disabled": yellow.component1, 261 - }, 262 - transitionDuration: animationDuration.fast, 263 - transitionProperty: "background-color, border-color", 264 - transitionTimingFunction: "ease-in-out", 265 - }, 266 - bgUi: { 267 - backgroundColor: { 268 - default: yellow.component1, 269 - ":active:not(:disabled)": yellow.component3, 270 - ":hover:not(:has(* button:hover)):not(:disabled)": yellow.component2, 271 - ":disabled": yellow.component1, 272 - }, 273 - transitionDuration: animationDuration.fast, 274 - transitionProperty: "background-color, border-color", 275 - transitionTimingFunction: "ease-in-out", 276 - }, 277 - bgAction: { 278 - backgroundColor: { 279 - default: yellow.component2, 280 - ":active:not(:disabled)": yellow.component3, 281 - ":hover:not(:has(* button:hover)):not(:disabled)": yellow.component3, 282 - ":disabled": yellow.component1, 283 - }, 284 - transitionDuration: animationDuration.fast, 285 - transitionProperty: "background-color, border-color", 286 - transitionTimingFunction: "ease-in-out", 287 - }, 288 - bgSolidAction: { 289 - backgroundColor: { 290 - default: yellow.solid1, 291 - ":hover:not(:has(* button:hover)):not(:disabled)": yellow.solid2, 292 - ":disabled": yellow.component1, 293 - }, 294 - transitionDuration: animationDuration.fast, 295 - transitionProperty: "background-color, border-color", 296 - transitionTimingFunction: "ease-in-out", 297 - }, 298 - }); 299 - 300 - // eslint-disable-next-line @stylexjs/enforce-extension 301 - export const success = stylex.create({ 302 - bg: { backgroundColor: green.bg1 }, 303 - bgSubtle: { backgroundColor: green.bg2 }, 304 - bgDim: { backgroundColor: green.component1 }, 305 - bgSecondary: { backgroundColor: green.component2 }, 306 - bgActive: { backgroundColor: green.component3 }, 307 - borderDim: { 308 - borderColor: green.border1, 309 - borderStyle: "solid", 310 - borderWidth: 1, 311 - }, 312 - border: { 313 - borderColor: green.border2, 314 - borderStyle: "solid", 315 - borderWidth: 1, 316 - }, 317 - borderInteractive: { 318 - borderColor: { 319 - default: green.border2, 320 - ":hover": green.border3, 321 - }, 322 - borderStyle: "solid", 323 - borderWidth: 1, 324 - transitionDuration: animationDuration.fast, 325 - transitionProperty: "background-color, border-color", 326 - transitionTimingFunction: "ease-in-out", 327 - }, 328 - bgSolid: { backgroundColor: green.solid1 }, 329 - bgSolidDark: { backgroundColor: green.solid2 }, 330 - textDim: { color: green.text1, fontFamily: fontFamily["sans"] }, 331 - text: { color: green.text2, fontFamily: fontFamily["sans"] }, 332 - textContrast: { color: "white" }, 333 - 334 - bgGhost: { 335 - backgroundColor: { 336 - default: "transparent", 337 - ":active:not(:disabled)": green.component3, 338 - ":hover:not(:has(* button:hover)):not(:disabled)": green.component2, 339 - ":disabled": green.component1, 340 - }, 341 - transitionDuration: animationDuration.fast, 342 - transitionProperty: "background-color, border-color", 343 - transitionTimingFunction: "ease-in-out", 344 - }, 345 - bgUi: { 346 - backgroundColor: { 347 - default: green.component1, 348 - ":active:not(:disabled)": green.component3, 349 - ":hover:not(:has(* button:hover)):not(:disabled)": green.component2, 350 - ":disabled": green.component1, 351 - }, 352 - transitionDuration: animationDuration.fast, 353 - transitionProperty: "background-color, border-color", 354 - transitionTimingFunction: "ease-in-out", 355 - }, 356 - bgAction: { 357 - backgroundColor: { 358 - default: green.component2, 359 - ":active:not(:disabled)": green.component3, 360 - ":hover:not(:has(* button:hover)):not(:disabled)": green.component3, 361 - ":disabled": green.component1, 362 - }, 363 - transitionDuration: animationDuration.fast, 364 - transitionProperty: "background-color, border-color", 365 - transitionTimingFunction: "ease-in-out", 366 - }, 367 - bgSolidAction: { 368 - backgroundColor: { 369 - default: green.solid1, 370 - ":hover:not(:has(* button:hover)):not(:disabled)": green.solid2, 371 - ":disabled": green.component1, 372 - }, 373 - transitionDuration: animationDuration.fast, 374 - transitionProperty: "background-color, border-color", 375 - transitionTimingFunction: "ease-in-out", 376 - }, 377 - });
-12
apps/example/src/components/theme/shadow.stylex.tsx
··· 1 - import * as stylex from "@stylexjs/stylex"; 2 - 3 - export const shadow = stylex.defineVars({ 4 - "2xs": "0 1px rgb(0 0 0 / 0.05)", 5 - xs: "0 1px 2px 0 rgb(0 0 0 / 0.05)", 6 - sm: "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)", 7 - md: "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)", 8 - lg: "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)", 9 - xl: "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)", 10 - "2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)", 11 - none: "0 0 #0000", 12 - });
-42
apps/example/src/components/theme/spacing.stylex.tsx
··· 1 - import * as stylex from "@stylexjs/stylex"; 2 - 3 - export const spacing = stylex.defineVars({ 4 - px: "1px", 5 - "0": "0px", 6 - "0.5": "0.125rem", 7 - "1": "0.25rem", 8 - "1.5": "0.375rem", 9 - "2": "0.5rem", 10 - "2.5": "0.625rem", 11 - "3": "0.75rem", 12 - "3.5": "0.875rem", 13 - "4": "1rem", 14 - "5": "1.25rem", 15 - "6": "1.5rem", 16 - "7": "1.75rem", 17 - "8": "2rem", 18 - "9": "2.25rem", 19 - "10": "2.5rem", 20 - "11": "2.75rem", 21 - "12": "3rem", 22 - "14": "3.5rem", 23 - "16": "4rem", 24 - "20": "5rem", 25 - "24": "6rem", 26 - "28": "7rem", 27 - "32": "8rem", 28 - "36": "9rem", 29 - "40": "10rem", 30 - "44": "11rem", 31 - "48": "12rem", 32 - "52": "13rem", 33 - "56": "14rem", 34 - "60": "15rem", 35 - "64": "16rem", 36 - "72": "18rem", 37 - "80": "20rem", 38 - "96": "24rem", 39 - }); 40 - 41 - // eslint-disable-next-line @stylexjs/enforce-extension 42 - export type Spacing = keyof typeof spacing;
-167
apps/example/src/components/theme/typography.stylex.tsx
··· 1 - import * as stylex from "@stylexjs/stylex"; 2 - 3 - import { breakpoints } from "./breakpoints.stylex"; 4 - import { spacing } from "./spacing.stylex"; 5 - 6 - export const fontFamily = stylex.defineVars({ 7 - sans: "Inter, sans-serif", 8 - serif: "Georgia, serif", 9 - mono: "Monaco, monospace", 10 - }); 11 - 12 - export const fontWeight = stylex.defineVars({ 13 - thin: "100", 14 - extralight: "200", 15 - light: "300", 16 - normal: "400", 17 - medium: "500", 18 - semibold: "600", 19 - bold: "700", 20 - extrabold: "800", 21 - black: "900", 22 - }); 23 - 24 - export const fontSize = stylex.defineVars({ 25 - xs: "0.75rem", 26 - sm: "0.85rem", 27 - base: "1rem", 28 - lg: "1.125rem", 29 - xl: "1.25rem", 30 - "2xl": "1.5rem", 31 - "3xl": "1.875rem", 32 - "4xl": "2.25rem", 33 - "5xl": "3rem", 34 - "6xl": "3.75rem", 35 - "7xl": "4.5rem", 36 - "8xl": "6rem", 37 - "9xl": "8rem", 38 - }); 39 - 40 - export const lineHeight = stylex.defineVars({ 41 - none: "1", 42 - xs: "1", 43 - sm: "1.25", 44 - base: "calc(1.5 / 1)", 45 - lg: "calc(1.75 / 1.125)", 46 - xl: "calc(1.75 / 1.25)", 47 - "2xl": "calc(2 / 1.5)", 48 - "3xl": "calc(2.25 / 1.875)", 49 - "4xl": "calc(2.5 / 2.25)", 50 - "5xl": "1", 51 - "6xl": "1", 52 - "7xl": "1", 53 - "8xl": "1", 54 - "9xl": "1", 55 - }); 56 - 57 - export const tracking = stylex.defineVars({ 58 - tighter: "-0.05em", 59 - tight: "-0.025em", 60 - normal: "0em", 61 - wide: "0.025em", 62 - wider: "0.05em", 63 - widest: "0.1em", 64 - }); 65 - 66 - // eslint-disable-next-line @stylexjs/enforce-extension 67 - export const typeramp = stylex.create({ 68 - heading1: { 69 - margin: 0, 70 - // eslint-disable-next-line @stylexjs/valid-styles 71 - fontFamily: fontFamily["sans"], 72 - fontSize: { 73 - default: fontSize["4xl"], 74 - [breakpoints["md"]]: fontSize["5xl"], 75 - }, 76 - // eslint-disable-next-line @stylexjs/valid-styles 77 - fontWeight: fontWeight["extrabold"], 78 - letterSpacing: tracking["tight"], 79 - lineHeight: { 80 - default: lineHeight["4xl"], 81 - [breakpoints["md"]]: lineHeight["5xl"], 82 - }, 83 - scrollMarginBlockStart: spacing["20"], 84 - }, 85 - heading2: { 86 - margin: 0, 87 - // eslint-disable-next-line @stylexjs/valid-styles 88 - fontFamily: fontFamily["sans"], 89 - fontSize: { 90 - default: fontSize["3xl"], 91 - [breakpoints["md"]]: fontSize["4xl"], 92 - }, 93 - // eslint-disable-next-line @stylexjs/valid-styles 94 - fontWeight: fontWeight["semibold"], 95 - letterSpacing: tracking["tight"], 96 - lineHeight: { 97 - default: lineHeight["3xl"], 98 - [breakpoints["md"]]: lineHeight["4xl"], 99 - }, 100 - scrollMarginBlockStart: spacing["20"], 101 - borderBottomWidth: 1, 102 - paddingBottom: spacing["2"], 103 - }, 104 - heading3: { 105 - margin: 0, 106 - // eslint-disable-next-line @stylexjs/valid-styles 107 - fontFamily: fontFamily["sans"], 108 - fontSize: { default: fontSize["2xl"] }, 109 - // eslint-disable-next-line @stylexjs/valid-styles 110 - fontWeight: fontWeight["semibold"], 111 - letterSpacing: tracking["tight"], 112 - lineHeight: { default: lineHeight["2xl"] }, 113 - scrollMarginBlockStart: spacing["20"], 114 - }, 115 - heading4: { 116 - margin: 0, 117 - // eslint-disable-next-line @stylexjs/valid-styles 118 - fontFamily: fontFamily["sans"], 119 - fontSize: { default: fontSize["xl"] }, 120 - // eslint-disable-next-line @stylexjs/valid-styles 121 - fontWeight: fontWeight["semibold"], 122 - letterSpacing: tracking["tight"], 123 - lineHeight: { default: lineHeight["xl"] }, 124 - scrollMarginBlockStart: spacing["20"], 125 - }, 126 - heading5: { 127 - // eslint-disable-next-line @stylexjs/valid-styles 128 - fontFamily: fontFamily["sans"], 129 - fontSize: { default: fontSize["lg"] }, 130 - // eslint-disable-next-line @stylexjs/valid-styles 131 - fontWeight: fontWeight["semibold"], 132 - letterSpacing: tracking["tight"], 133 - lineHeight: { default: lineHeight["lg"] }, 134 - }, 135 - body: { 136 - margin: 0, 137 - // eslint-disable-next-line @stylexjs/valid-styles 138 - fontFamily: fontFamily["sans"], 139 - fontSize: { default: fontSize["base"] }, 140 - lineHeight: spacing["7"], 141 - }, 142 - smallBody: { 143 - margin: 0, 144 - // eslint-disable-next-line @stylexjs/valid-styles 145 - fontFamily: fontFamily["sans"], 146 - fontSize: { default: fontSize["sm"] }, 147 - lineHeight: { default: lineHeight["sm"] }, 148 - }, 149 - label: { 150 - // eslint-disable-next-line @stylexjs/valid-styles 151 - fontFamily: fontFamily["sans"], 152 - fontSize: { default: fontSize["sm"] }, 153 - // eslint-disable-next-line @stylexjs/valid-styles 154 - fontWeight: fontWeight["semibold"], 155 - letterSpacing: tracking["tight"], 156 - lineHeight: { default: lineHeight["sm"] }, 157 - }, 158 - sublabel: { 159 - margin: 0, 160 - // eslint-disable-next-line @stylexjs/valid-styles 161 - fontFamily: fontFamily["sans"], 162 - fontSize: { default: fontSize["xs"] }, 163 - // eslint-disable-next-line @stylexjs/valid-styles 164 - fontWeight: fontWeight["medium"], 165 - lineHeight: { default: lineHeight["xs"] }, 166 - }, 167 - });
-186
apps/example/src/components/theme/useButtonStyles.ts
··· 1 - "use client"; 2 - 3 - import * as stylex from "@stylexjs/stylex"; 4 - import { use } from "react"; 5 - 6 - import type { ButtonVariant, Size } from "../types"; 7 - 8 - import { ButtonGroupContext } from "../button/context"; 9 - import { SizeContext } from "../context"; 10 - import { animationDuration } from "./animations.stylex"; 11 - import { slate } from "./colors.stylex"; 12 - import { radius } from "./radius.stylex"; 13 - import { critical, gray, primary } from "./semantic-color.stylex"; 14 - import { shadow } from "./shadow.stylex"; 15 - import { spacing } from "./spacing.stylex"; 16 - import { 17 - fontFamily, 18 - fontSize, 19 - fontWeight, 20 - lineHeight, 21 - } from "./typography.stylex"; 22 - 23 - const styles = stylex.create({ 24 - shadow: { 25 - boxShadow: shadow["xs"], 26 - }, 27 - base: { 28 - borderRadius: radius["md"], 29 - borderStyle: "solid", 30 - borderWidth: 1, 31 - gap: spacing["1"], 32 - alignItems: "center", 33 - boxSizing: "border-box", 34 - display: "inline-flex", 35 - flexShrink: 0, 36 - fontFamily: fontFamily["sans"], 37 - fontWeight: fontWeight["medium"], 38 - justifyContent: "center", 39 - opacity: { 40 - ":disabled": 0.5, 41 - }, 42 - pointerEvents: { 43 - ":disabled": "none", 44 - }, 45 - transitionDuration: animationDuration.fast, 46 - transitionProperty: "all", 47 - transitionTimingFunction: "ease-in-out", 48 - whiteSpace: "nowrap", 49 - 50 - // eslint-disable-next-line @stylexjs/no-legacy-contextual-styles, @stylexjs/valid-styles 51 - ":is(*) svg": { 52 - flexShrink: 0, 53 - pointerEvents: "none", 54 - height: spacing["4"], 55 - width: spacing["4"], 56 - }, 57 - }, 58 - small: { 59 - fontSize: fontSize["xs"], 60 - lineHeight: lineHeight["xs"], 61 - height: spacing["7"], 62 - paddingLeft: { 63 - default: spacing["2"], 64 - }, 65 - paddingRight: spacing["2"], 66 - 67 - // eslint-disable-next-line @stylexjs/no-legacy-contextual-styles, @stylexjs/valid-styles 68 - ":is(*) svg": { 69 - flexShrink: 0, 70 - pointerEvents: "none", 71 - height: spacing["3.5"], 72 - width: spacing["3.5"], 73 - }, 74 - }, 75 - medium: { 76 - gap: spacing["1.5"], 77 - fontSize: fontSize["sm"], 78 - lineHeight: lineHeight["xs"], 79 - height: spacing["8"], 80 - paddingLeft: { 81 - default: spacing["3"], 82 - ":has(svg+*)": spacing["2.5"], 83 - }, 84 - paddingRight: spacing["3"], 85 - }, 86 - large: { 87 - gap: spacing["2"], 88 - height: spacing["10"], 89 - paddingLeft: { 90 - default: spacing["4"], 91 - ":has(svg+*)": spacing["3"], 92 - }, 93 - paddingRight: spacing["4"], 94 - }, 95 - outline: { 96 - borderWidth: 1, 97 - }, 98 - secondary: { 99 - borderColor: { 100 - default: slate.component1, 101 - ":hover": slate.component2, 102 - ":active": slate.component3, 103 - }, 104 - }, 105 - tertiary: { 106 - borderColor: { 107 - default: "transparent", 108 - ":hover": slate.component2, 109 - ":active": slate.component3, 110 - }, 111 - }, 112 - 113 - groupHorizontal: { 114 - borderBottomLeftRadius: { ":not(:first-child)": 0 }, 115 - borderBottomRightRadius: { ":not(:last-child)": 0 }, 116 - borderLeftWidth: { ":not(:first-child)": 0 }, 117 - borderTopLeftRadius: { ":not(:first-child)": 0 }, 118 - borderTopRightRadius: { ":not(:last-child)": 0 }, 119 - }, 120 - secondaryGroupHorizontal: { 121 - borderRightColor: { ":not(:last-child)": slate.border2 }, 122 - }, 123 - groupVertical: { 124 - borderBottomLeftRadius: { ":not(:last-child)": 0 }, 125 - borderBottomRightRadius: { ":not(:last-child)": 0 }, 126 - borderTopLeftRadius: { ":not(:first-child)": 0 }, 127 - borderTopRightRadius: { ":not(:first-child)": 0 }, 128 - borderTopWidth: { ":not(:first-child)": 0 }, 129 - }, 130 - secondaryGroupVertical: { 131 - borderBottomColor: { ":not(:last-child)": slate.border2 }, 132 - }, 133 - }); 134 - 135 - export const useButtonStyles = ({ 136 - variant = "primary", 137 - size: sizeProp, 138 - }: { 139 - variant?: ButtonVariant; 140 - size?: Size; 141 - }) => { 142 - const size = sizeProp || use(SizeContext); 143 - const group = use(ButtonGroupContext); 144 - 145 - return [ 146 - styles.base, 147 - group === "horizontal" && styles.groupHorizontal, 148 - group === "vertical" && styles.groupVertical, 149 - variant === "primary" && [ 150 - primary.bgAction, 151 - primary.borderInteractive, 152 - primary.text, 153 - styles.shadow, 154 - ], 155 - variant === "secondary" && [ 156 - gray.bgUi, 157 - styles.secondary, 158 - gray.text, 159 - group === "horizontal" && styles.secondaryGroupHorizontal, 160 - group === "vertical" && styles.secondaryGroupVertical, 161 - ], 162 - variant === "tertiary" && [ 163 - gray.bgGhost, 164 - styles.tertiary, 165 - gray.text, 166 - group === "horizontal" && styles.secondaryGroupHorizontal, 167 - group === "vertical" && styles.secondaryGroupVertical, 168 - ], 169 - variant === "outline" && [ 170 - gray.borderInteractive, 171 - gray.bgGhost, 172 - gray.text, 173 - styles.outline, 174 - styles.shadow, 175 - ], 176 - variant === "critical" && [ 177 - critical.bgSolidAction, 178 - critical.borderInteractive, 179 - critical.textContrast, 180 - styles.shadow, 181 - ], 182 - size === "sm" && styles.small, 183 - size === "md" && styles.medium, 184 - size === "lg" && styles.large, 185 - ]; 186 - };
-88
apps/example/src/components/theme/useDialogStyles.ts
··· 1 - import * as stylex from "@stylexjs/stylex"; 2 - import { use } from "react"; 3 - 4 - import type { Size } from "../types"; 5 - 6 - import { SizeContext } from "../context"; 7 - import { animationDuration, animations } from "../theme/animations.stylex"; 8 - import { radius } from "../theme/radius.stylex"; 9 - import { shadow } from "../theme/shadow.stylex"; 10 - import { gray } from "./semantic-color.stylex"; 11 - 12 - const styles = stylex.create({ 13 - overlay: { 14 - backgroundColor: "rgba(0, 0, 0, 0.5)", 15 - position: "absolute", 16 - zIndex: 100, 17 - height: "var(--page-height)", 18 - left: 0, 19 - top: 0, 20 - width: "100vw", 21 - 22 - animationDuration: animationDuration.slow, 23 - animationName: { 24 - ":is([data-entering])": animations.fadeIn, 25 - }, 26 - animationTimingFunction: "ease-in", 27 - opacity: { 28 - default: 1, 29 - ":is([data-exiting])": 0, 30 - }, 31 - transitionDuration: { 32 - ":is([data-exiting])": animationDuration.fast, 33 - }, 34 - transitionProperty: "opacity", 35 - transitionTimingFunction: "ease-in-out", 36 - }, 37 - modal: { 38 - borderRadius: radius["lg"], 39 - outline: "none", 40 - boxShadow: shadow["lg"], 41 - display: "flex", 42 - flexDirection: "column", 43 - position: "fixed", 44 - translate: "-50% -50%", 45 - left: "50%", 46 - maxHeight: "calc(var(--visual-viewport-height) * 0.8)", 47 - top: "calc(var(--visual-viewport-height) / 2)", 48 - 49 - animationDuration: { ":is([data-entering])": animationDuration.verySlow }, 50 - animationName: { ":is([data-entering])": animations.zoomIn }, 51 - animationTimingFunction: { 52 - ":is([data-entering])": "cubic-bezier(0.175, 0.885, 0.32, 1.275)", 53 - }, 54 - }, 55 - dialog: { 56 - outline: "none", 57 - display: "flex", 58 - flexDirection: "column", 59 - flexGrow: 1, 60 - minHeight: 0, 61 - }, 62 - sm: { 63 - width: 400, 64 - }, 65 - md: { 66 - width: 600, 67 - }, 68 - lg: { 69 - width: 800, 70 - }, 71 - }); 72 - 73 - export function useDialogStyles({ size: sizeProp }: { size?: Size }) { 74 - const size = sizeProp || use(SizeContext); 75 - 76 - return { 77 - overlay: styles.overlay, 78 - modal: [ 79 - styles.modal, 80 - styles.modal, 81 - gray.bg, 82 - gray.text, 83 - gray.border, 84 - styles[size], 85 - ], 86 - dialog: styles.dialog, 87 - }; 88 - }
-114
apps/example/src/components/theme/useInputStyles.ts
··· 1 - import * as stylex from "@stylexjs/stylex"; 2 - import { use } from "react"; 3 - 4 - import type { Size } from "../types"; 5 - 6 - import { SizeContext } from "../context"; 7 - import { slate } from "./colors.stylex"; 8 - import { radius } from "./radius.stylex"; 9 - import { gray } from "./semantic-color.stylex"; 10 - import { spacing } from "./spacing.stylex"; 11 - import { fontSize, lineHeight } from "./typography.stylex"; 12 - 13 - const styles = stylex.create({ 14 - field: { 15 - gap: spacing["2"], 16 - display: "flex", 17 - flexDirection: "column", 18 - }, 19 - addon: { 20 - color: gray.textDim, 21 - flexShrink: 0, 22 - height: "100%", 23 - minWidth: spacing["8"], 24 - paddingLeft: { ":first-child": spacing["0.5"] }, 25 - paddingRight: { 26 - ":last-child:has(svg)": spacing["0.5"], 27 - ":last-child": spacing["2"], 28 - }, 29 - 30 - gap: spacing["0.5"], 31 - alignItems: "center", 32 - display: "flex", 33 - justifyContent: "center", 34 - 35 - // eslint-disable-next-line @stylexjs/no-legacy-contextual-styles, @stylexjs/valid-styles 36 - ":is(*) svg": { 37 - flexShrink: 0, 38 - pointerEvents: "none", 39 - height: spacing["4"], 40 - width: spacing["4"], 41 - }, 42 - }, 43 - inputWrapper: { 44 - padding: 0, 45 - borderRadius: radius["md"], 46 - overflow: "hidden", 47 - boxSizing: "border-box", 48 - display: "flex", 49 - lineHeight: lineHeight["none"], 50 - 51 - borderColor: { 52 - default: slate.border2, 53 - ":hover": slate.border3, 54 - ":focus": slate.solid1, 55 - }, 56 - borderStyle: "solid", 57 - borderWidth: 1, 58 - 59 - transitionProperty: "background-color, border-color", 60 - }, 61 - input: { 62 - borderWidth: 0, 63 - outline: "none", 64 - alignItems: "center", 65 - backgroundColor: "transparent", 66 - boxSizing: "border-box", 67 - color: { 68 - ":is(::placeholder,[data-placeholder])": slate.text1, 69 - }, 70 - display: "flex", 71 - flexGrow: 1, 72 - lineHeight: lineHeight["none"], 73 - 74 - appearance: { 75 - "::-webkit-search-cancel-button": "none", 76 - "::-webkit-search-decoration": "none", 77 - }, 78 - }, 79 - sm: { 80 - height: spacing["6"], 81 - }, 82 - smInput: { 83 - fontSize: fontSize["xs"], 84 - paddingLeft: { ":first-child": spacing["1"] }, 85 - paddingRight: spacing["1"], 86 - }, 87 - md: { 88 - height: spacing["8"], 89 - }, 90 - mdInput: { 91 - fontSize: fontSize["sm"], 92 - paddingLeft: { ":first-child": spacing["2"] }, 93 - paddingRight: spacing["2"], 94 - }, 95 - lg: { 96 - height: spacing["10"], 97 - }, 98 - lgInput: { 99 - fontSize: fontSize["base"], 100 - paddingLeft: spacing["1"], 101 - paddingRight: spacing["2"], 102 - }, 103 - }); 104 - 105 - export function useInputStyles({ size: sizeProp }: { size?: Size }) { 106 - const size = sizeProp || use(SizeContext); 107 - 108 - return { 109 - field: [styles.field], 110 - wrapper: [styles.inputWrapper, gray.bgUi, gray.text, styles[size]], 111 - input: [styles.input, styles[`${size}Input`]], 112 - addon: styles.addon as unknown as stylex.StyleXStyles, 113 - }; 114 - }
-114
apps/example/src/components/theme/useListBoxItemStyles.ts
··· 1 - import * as stylex from "@stylexjs/stylex"; 2 - import { use } from "react"; 3 - 4 - import { SizeContext } from "../context"; 5 - import { animationDuration } from "../theme/animations.stylex"; 6 - import { plum, slate } from "../theme/colors.stylex"; 7 - import { radius } from "../theme/radius.stylex"; 8 - import { spacing } from "../theme/spacing.stylex"; 9 - import { 10 - fontSize, 11 - fontWeight, 12 - lineHeight, 13 - typeramp, 14 - } from "../theme/typography.stylex"; 15 - 16 - const styles = stylex.create({ 17 - item: { 18 - display: "flex", 19 - userSelect: "none", 20 - 21 - outline: { 22 - default: "none", 23 - ":focus": "none", 24 - }, 25 - boxSizing: "border-box", 26 - fontWeight: fontWeight["medium"], 27 - paddingBottom: spacing["0.5"], 28 - paddingLeft: spacing["1"], 29 - paddingRight: spacing["1"], 30 - paddingTop: spacing["0.5"], 31 - }, 32 - sm: { minHeight: spacing["7"] }, 33 - md: { minHeight: spacing["9"] }, 34 - lg: { minHeight: spacing["12"] }, 35 - itemInner: { 36 - borderRadius: radius["md"], 37 - gap: spacing["3"], 38 - alignItems: "center", 39 - backgroundColor: { 40 - default: "transparent", 41 - [":is([data-react-aria-pressable=true]:hover:not([data-disabled]) *)"]: 42 - slate.component2, 43 - [":is([data-react-aria-pressable=true]:not([data-disabled]):active *)"]: 44 - slate.component3, 45 - [":is([data-react-aria-pressable=true][data-focused] *)"]: 46 - slate.component2, 47 - [":is([data-react-aria-pressable=true][data-selected=true] *)"]: 48 - slate.component2, 49 - }, 50 - boxSizing: "border-box", 51 - color: { 52 - default: slate.text2, 53 - [":is([data-react-aria-pressable=true][data-disabled] *)"]: slate.border3, 54 - }, 55 - display: "flex", 56 - flexGrow: 1, 57 - transitionDuration: animationDuration.fast, 58 - transitionProperty: "background-color", 59 - transitionTimingFunction: "ease-in-out", 60 - paddingBottom: spacing["2"], 61 - paddingLeft: spacing["3"], 62 - paddingRight: spacing["3"], 63 - paddingTop: spacing["2"], 64 - }, 65 - smItemInner: { 66 - gap: spacing["2"], 67 - fontSize: fontSize["xs"], 68 - lineHeight: lineHeight["xs"], 69 - paddingBottom: spacing["1"], 70 - paddingTop: spacing["1"], 71 - }, 72 - lgItemInner: { 73 - fontSize: fontSize["base"], 74 - }, 75 - check: { 76 - color: plum.solid1, 77 - }, 78 - addon: { 79 - alignItems: "center", 80 - display: "flex", 81 - justifyContent: "center", 82 - minWidth: spacing["4"], 83 - 84 - // eslint-disable-next-line @stylexjs/no-legacy-contextual-styles, @stylexjs/valid-styles 85 - ":is(*) svg": { 86 - flexShrink: 0, 87 - pointerEvents: "none", 88 - height: spacing["4"], 89 - width: spacing["4"], 90 - }, 91 - }, 92 - label: { 93 - gap: spacing["1.5"], 94 - display: "flex", 95 - flexDirection: "column", 96 - flexGrow: 1, 97 - }, 98 - }); 99 - 100 - export function useListBoxItemStyles() { 101 - const size = use(SizeContext); 102 - 103 - return { 104 - wrapper: [typeramp.label, styles.item, styles[size]], 105 - inner: [ 106 - styles.itemInner, 107 - size === "sm" && styles.smItemInner, 108 - size === "lg" && styles.lgItemInner, 109 - ], 110 - label: styles.label, 111 - addon: styles.addon, 112 - check: styles.check, 113 - }; 114 - }
-24
apps/example/src/components/theme/usePopoverStyles.ts
··· 1 - import * as stylex from "@stylexjs/stylex"; 2 - 3 - import { radius } from "./radius.stylex"; 4 - import { gray } from "./semantic-color.stylex"; 5 - import { shadow } from "./shadow.stylex"; 6 - import { spacing } from "./spacing.stylex"; 7 - 8 - const styles = stylex.create({ 9 - popover: { 10 - borderRadius: radius["md"], 11 - outline: "none", 12 - overflow: "auto", 13 - boxShadow: shadow["md"], 14 - minWidth: spacing["40"], 15 - 16 - paddingBottom: spacing["1"], 17 - paddingTop: spacing["1"], 18 - }, 19 - }); 20 - 21 - // eslint-disable-next-line @eslint-react/no-unnecessary-use-prefix 22 - export function usePopoverStyles() { 23 - return [styles.popover, gray.bgSubtle, gray.text, gray.border]; 24 - }
-73
apps/example/src/components/time-field/index.tsx
··· 1 - import type { 2 - TimeFieldProps as AriaTimeFieldProps, 3 - TimeValue, 4 - ValidationResult, 5 - } from "react-aria-components"; 6 - 7 - import * as stylex from "@stylexjs/stylex"; 8 - import { useRef } from "react"; 9 - import { 10 - TimeField as AriaTimeField, 11 - DateInput, 12 - DateSegment, 13 - FieldError, 14 - } from "react-aria-components"; 15 - 16 - import type { Size } from "../types"; 17 - 18 - import { Description, Label } from "../label"; 19 - import { useInputStyles } from "../theme/useInputStyles"; 20 - 21 - export interface TimeFieldProps<T extends TimeValue> extends Omit< 22 - AriaTimeFieldProps<T>, 23 - "style" | "className" 24 - > { 25 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 26 - label?: React.ReactNode; 27 - description?: string; 28 - errorMessage?: string | ((validation: ValidationResult) => string); 29 - size?: Size; 30 - prefix?: React.ReactNode; 31 - suffix?: React.ReactNode; 32 - } 33 - 34 - export function TimeField<T extends TimeValue>({ 35 - label, 36 - description, 37 - errorMessage, 38 - style, 39 - size, 40 - prefix, 41 - suffix, 42 - ...props 43 - }: TimeFieldProps<T>) { 44 - const inputRef = useRef<HTMLInputElement>(null); 45 - const inputStyles = useInputStyles({ size }); 46 - 47 - return ( 48 - <AriaTimeField {...props} {...stylex.props(inputStyles.field, style)}> 49 - {label !== null && <Label size={size}>{label}</Label>} 50 - {/* 51 - This onClick is specifically for mouse users not clicking directly on the input. 52 - A keyboard user would not encounter the same issue. 53 - */} 54 - {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} 55 - <div 56 - {...stylex.props(inputStyles.wrapper)} 57 - onClick={() => inputRef.current?.focus()} 58 - > 59 - {prefix !== null && ( 60 - <div {...stylex.props(inputStyles.addon)}>{prefix}</div> 61 - )} 62 - <DateInput {...stylex.props(inputStyles.input)} ref={inputRef}> 63 - {(segment) => <DateSegment segment={segment} />} 64 - </DateInput> 65 - {suffix !== null && ( 66 - <div {...stylex.props(inputStyles.addon)}>{suffix}</div> 67 - )} 68 - </div> 69 - {description && <Description size={size}>{description}</Description>} 70 - <FieldError>{errorMessage}</FieldError> 71 - </AriaTimeField> 72 - ); 73 - }
-86
apps/example/src/components/toggle-button-group/index.tsx
··· 1 - "use client"; 2 - 3 - import type { ToggleButtonGroupProps as AriaToggleButtonGroupProps } from "react-aria-components"; 4 - 5 - import * as stylex from "@stylexjs/stylex"; 6 - import { use } from "react"; 7 - import { ToggleButtonGroup as AriaToggleButtonGroup } from "react-aria-components"; 8 - 9 - import { ButtonGroupContext } from "../button/context"; 10 - 11 - const styles = stylex.create({ 12 - group: { 13 - alignItems: "center", 14 - display: "flex", 15 - }, 16 - horizontal: { 17 - flexDirection: "row", 18 - }, 19 - vertical: { 20 - flexDirection: "column", 21 - }, 22 - contents: { 23 - display: "contents", 24 - }, 25 - horizontalContents: { 26 - borderBottomLeftRadius: { ":is(:not(:first-child)) *": "0" }, 27 - borderBottomRightRadius: { ":is(:not(:last-child)) *": "0" }, 28 - borderLeftWidth: { ":is(:not(:first-child)) *": "0" }, 29 - borderRightWidth: { ":is(:not(:last-child)) *": "0" }, 30 - borderTopLeftRadius: { ":is(:not(:first-child)) *": "0" }, 31 - borderTopRightRadius: { ":is(:not(:last-child)) *": "0" }, 32 - }, 33 - verticalContents: { 34 - // eslint-disable-next-line @stylexjs/valid-styles 35 - borderBottomLeftWidth: { ":is(:not(:first-child)) *": "0" }, 36 - borderBottomRightRadius: { ":is(:not(:last-child)) *": "0" }, 37 - borderBottomWidth: { ":is(:not(:last-child)) *": "0" }, 38 - borderTopLeftRadius: { ":is(:not(:first-child)) *": "0" }, 39 - borderTopRightRadius: { ":is(:not(:first-child)) *": "0" }, 40 - borderTopWidth: { ":is(:not(:first-child)) *": "0" }, 41 - }, 42 - }); 43 - 44 - interface ToggleButtonGroupProps extends Omit< 45 - AriaToggleButtonGroupProps, 46 - "className" | "style" | "children" 47 - > { 48 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 49 - orientation?: "horizontal" | "vertical"; 50 - children?: React.ReactNode; 51 - } 52 - 53 - export const ToggleButtonGroup = ({ 54 - children, 55 - style, 56 - orientation: orientationProp = "horizontal", 57 - ...props 58 - }: ToggleButtonGroupProps) => { 59 - const groupOrientation = use(ButtonGroupContext); 60 - const isInGroup = groupOrientation !== undefined; 61 - const orientation = groupOrientation || orientationProp; 62 - 63 - return ( 64 - <ButtonGroupContext value={orientation}> 65 - <AriaToggleButtonGroup 66 - {...stylex.props( 67 - isInGroup 68 - ? [ 69 - styles.contents, 70 - orientation === "horizontal" && styles.horizontalContents, 71 - orientation === "vertical" && styles.verticalContents, 72 - ] 73 - : [ 74 - styles.group, 75 - orientation === "horizontal" && styles.horizontal, 76 - orientation === "vertical" && styles.vertical, 77 - ], 78 - style, 79 - )} 80 - {...props} 81 - > 82 - {children} 83 - </AriaToggleButtonGroup> 84 - </ButtonGroupContext> 85 - ); 86 - };
-139
apps/example/src/components/toggle-button/index.tsx
··· 1 - import type { ToggleButtonProps as AriaToggleButtonProps } from "react-aria-components"; 2 - 3 - import * as stylex from "@stylexjs/stylex"; 4 - import { Children, use } from "react"; 5 - import { ToggleButton as AriaToggleButton } from "react-aria-components"; 6 - 7 - import type { ButtonVariant, Size } from "../types"; 8 - 9 - import { SizeContext } from "../context"; 10 - import { plum, slate } from "../theme/colors.stylex"; 11 - import { spacing } from "../theme/spacing.stylex"; 12 - import { useButtonStyles } from "../theme/useButtonStyles"; 13 - 14 - const styles = stylex.create({ 15 - primarySelected: { 16 - backgroundColor: { 17 - default: plum.solid1, 18 - ":hover": plum.solid2, 19 - ":active": plum.text1, 20 - }, 21 - color: "light-dark(white, black)", 22 - }, 23 - secondarySelected: { 24 - borderColor: { 25 - default: slate.border1, 26 - ":hover": slate.border2, 27 - ":active": slate.border3, 28 - }, 29 - backgroundColor: { 30 - default: slate.border1, 31 - ":hover": slate.border2, 32 - ":active": slate.border3, 33 - }, 34 - }, 35 - tertiarySelected: { 36 - borderColor: { 37 - default: slate.border1, 38 - ":hover": slate.border2, 39 - ":active": slate.border3, 40 - }, 41 - backgroundColor: { 42 - default: slate.border1, 43 - ":hover": slate.border2, 44 - ":active": slate.border3, 45 - }, 46 - }, 47 - outlineSelected: { 48 - borderColor: { 49 - default: slate.border1, 50 - ":hover": slate.border2, 51 - ":active": slate.border3, 52 - }, 53 - backgroundColor: { 54 - default: slate.border1, 55 - ":hover": slate.border2, 56 - ":active": slate.border3, 57 - }, 58 - }, 59 - sm: { 60 - paddingLeft: { 61 - ":has(> * + *, > *:not(svg):only-child)": spacing["2"], 62 - }, 63 - paddingRight: { 64 - ":has(> * + *, > *:not(svg):only-child)": spacing["2"], 65 - }, 66 - width: { 67 - ":has(svg:only-child)": spacing["7"], 68 - }, 69 - }, 70 - md: { 71 - paddingLeft: { 72 - ":has(> * + *, > *:not(svg):only-child)": spacing["3"], 73 - }, 74 - paddingRight: { 75 - ":has(> * + *, > *:not(svg):only-child)": spacing["3"], 76 - }, 77 - width: { 78 - ":has(svg:only-child)": spacing["8"], 79 - }, 80 - }, 81 - lg: { 82 - paddingLeft: { 83 - ":has(> * + *, > *:not(svg):only-child)": spacing["4"], 84 - }, 85 - paddingRight: { 86 - ":has(> * + *, > *:not(svg):only-child)": spacing["4"], 87 - }, 88 - width: { 89 - ":has(svg:only-child)": spacing["10"], 90 - }, 91 - }, 92 - }); 93 - 94 - export interface ToggleButtonProps extends Omit< 95 - AriaToggleButtonProps, 96 - "style" | "className" | "children" 97 - > { 98 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 99 - variant?: Exclude<ButtonVariant, "critical">; 100 - size?: Size; 101 - children?: React.ReactNode; 102 - } 103 - 104 - export function ToggleButton({ 105 - style, 106 - variant = "primary", 107 - size: sizeProp, 108 - children, 109 - ...props 110 - }: ToggleButtonProps) { 111 - const size = sizeProp || use(SizeContext); 112 - const buttonStyles = useButtonStyles({ variant, size }); 113 - const toggleButtonStyles = (isSelected?: boolean) => 114 - stylex.props( 115 - buttonStyles, 116 - styles[size], 117 - isSelected ? styles[`${variant}Selected`] : undefined, 118 - style, 119 - ); 120 - 121 - return ( 122 - <AriaToggleButton 123 - {...props} 124 - {...toggleButtonStyles()} 125 - className={({ isSelected }) => 126 - toggleButtonStyles(isSelected).className || "" 127 - } 128 - > 129 - {/* eslint-disable-next-line @eslint-react/no-children-map */} 130 - {Children.map(children, (child, index) => 131 - typeof child === "string" ? ( 132 - <span key={`${child}-${index.toString()}`}>{child}</span> 133 - ) : ( 134 - child 135 - ), 136 - )} 137 - </AriaToggleButton> 138 - ); 139 - }
-110
apps/example/src/components/tooltip/index.tsx
··· 1 - "use client"; 2 - 3 - import type { 4 - TooltipProps as AriaTooltipProps, 5 - TooltipTriggerComponentProps, 6 - } from "react-aria-components"; 7 - 8 - import * as stylex from "@stylexjs/stylex"; 9 - import { 10 - Tooltip as AriaTooltip, 11 - OverlayArrow, 12 - TooltipTrigger, 13 - } from "react-aria-components"; 14 - 15 - import { animationDuration } from "../theme/animations.stylex"; 16 - import { slateInverted } from "../theme/colors.stylex"; 17 - import { radius } from "../theme/radius.stylex"; 18 - import { shadow } from "../theme/shadow.stylex"; 19 - import { spacing } from "../theme/spacing.stylex"; 20 - import { fontFamily, fontSize, lineHeight } from "../theme/typography.stylex"; 21 - 22 - const tooltipStyle = stylex.create({ 23 - content: { 24 - borderRadius: radius["md"], 25 - backgroundColor: slateInverted.bg1, 26 - boxShadow: shadow["sm"], 27 - color: slateInverted.text1, 28 - fontFamily: fontFamily["sans"], 29 - fontSize: fontSize["sm"], 30 - lineHeight: lineHeight["sm"], 31 - paddingBottom: spacing["1"], 32 - paddingLeft: spacing["2"], 33 - paddingRight: spacing["2"], 34 - paddingTop: spacing["1"], 35 - 36 - "--origin": { 37 - ":is([data-placement=bottom])": "translateY(-4px)", 38 - ":is([data-placement=left])": "translateX(4px)", 39 - ":is([data-placement=right])": "translateX(-4px)", 40 - ":is([data-placement=top])": "translateY(4px)", 41 - }, 42 - opacity: { 43 - default: 1, 44 - ":is([data-entering])": 0, 45 - ":is([data-exiting])": 0, 46 - }, 47 - transform: { 48 - ":is([data-entering])": "scale(0.9) var(--origin)", 49 - ":is([data-exiting])": "scale(0.9) var(--origin)", 50 - }, 51 - transitionDuration: animationDuration.default, 52 - transitionProperty: "transform, opacity", 53 - }, 54 - caret: { 55 - fill: slateInverted.bg1, 56 - display: "flex", 57 - }, 58 - arrow: { 59 - transform: { 60 - [":is([data-placement=bottom] *)"]: "rotate(180deg)", 61 - [":is([data-placement=left] *)"]: "rotate(90deg)", 62 - [":is([data-placement=right] *)"]: "rotate(-90deg)", 63 - [":is([data-placement=top] *)"]: "rotate(0deg)", 64 - }, 65 - }, 66 - }); 67 - 68 - interface TooltipProps 69 - extends 70 - TooltipTriggerComponentProps, 71 - Pick<AriaTooltipProps, "crossOffset" | "placement" | "shouldFlip"> { 72 - text: string; 73 - children: React.ReactNode; 74 - } 75 - 76 - export const Tooltip = ({ 77 - text, 78 - children, 79 - crossOffset, 80 - placement, 81 - shouldFlip, 82 - ...triggerProps 83 - }: TooltipProps) => { 84 - return ( 85 - <TooltipTrigger {...triggerProps}> 86 - {children} 87 - 88 - <AriaTooltip 89 - {...stylex.props(tooltipStyle.content)} 90 - crossOffset={crossOffset} 91 - containerPadding={8} 92 - placement={placement} 93 - offset={8} 94 - shouldFlip={shouldFlip} 95 - > 96 - <OverlayArrow {...stylex.props(tooltipStyle.caret)}> 97 - <svg 98 - width={8} 99 - height={8} 100 - viewBox="0 0 8 8" 101 - {...stylex.props(tooltipStyle.arrow)} 102 - > 103 - <path d="M0 0 L4 4 L8 0" /> 104 - </svg> 105 - </OverlayArrow> 106 - {text} 107 - </AriaTooltip> 108 - </TooltipTrigger> 109 - ); 110 - };
-213
apps/example/src/components/tree/index.tsx
··· 1 - import type { 2 - TreeItemContentProps as AriaTreeItemContentProps, 3 - TreeItemProps as AriaTreeItemProps, 4 - TreeProps as AriaTreeProps, 5 - } from "react-aria-components"; 6 - 7 - import * as stylex from "@stylexjs/stylex"; 8 - import { ChevronRight, GripVertical } from "lucide-react"; 9 - import { use } from "react"; 10 - import { 11 - Tree as AriaTree, 12 - TreeItem as AriaTreeItem, 13 - TreeItemContent as AriaTreeItemContent, 14 - Button, 15 - } from "react-aria-components"; 16 - 17 - import type { Size } from "../types"; 18 - 19 - import { Checkbox } from "../checkbox"; 20 - import { SizeContext } from "../context"; 21 - import { animationDuration } from "../theme/animations.stylex"; 22 - import { radius } from "../theme/radius.stylex"; 23 - import { gray } from "../theme/semantic-color.stylex"; 24 - import { spacing } from "../theme/spacing.stylex"; 25 - import { useListBoxItemStyles } from "../theme/useListBoxItemStyles"; 26 - 27 - const styles = stylex.create({ 28 - wrapper: { 29 - position: "relative", 30 - }, 31 - itemInner: { 32 - gap: spacing["1"], 33 - }, 34 - spacer: { 35 - width: `calc((var(--tree-item-level, 0) - 1) * ${spacing["4"]})`, 36 - }, 37 - content: { 38 - gap: spacing["2"], 39 - alignItems: "center", 40 - display: "flex", 41 - flexGrow: 1, 42 - }, 43 - hidden: { 44 - opacity: 0, 45 - visibility: "hidden", 46 - }, 47 - chevron: { 48 - borderWidth: 0, 49 - backgroundColor: "transparent", 50 - transform: { 51 - default: "rotate(0deg)", 52 - ":is([aria-expanded=true] *)": "rotate(90deg)", 53 - }, 54 - paddingBottom: 0, 55 - paddingLeft: 0, 56 - paddingRight: 0, 57 - paddingTop: 0, 58 - }, 59 - addon: { 60 - marginBottom: `calc(${spacing["2"]} * -1)`, 61 - marginTop: `calc(${spacing["2"]} * -1)`, 62 - }, 63 - dragButtonWrapper: { 64 - opacity: { 65 - default: 0, 66 - ":is([data-react-aria-pressable=true]:hover:not([data-disabled]) *)": 1, 67 - ":hover": 1, 68 - }, 69 - position: "absolute", 70 - transform: "translate(-100%, -50%)", 71 - transitionDuration: animationDuration.fast, 72 - transitionProperty: "opacity", 73 - transitionTimingFunction: "ease-in-out", 74 - left: 0, 75 - top: "50%", 76 - }, 77 - dragButton: { 78 - borderRadius: radius["sm"], 79 - alignItems: "center", 80 - display: "flex", 81 - justifyContent: "center", 82 - 83 - height: spacing["8"], 84 - width: spacing["8"], 85 - }, 86 - }); 87 - 88 - interface TreeItemContentProps extends Omit< 89 - AriaTreeItemContentProps, 90 - "children" 91 - > { 92 - children?: React.ReactNode; 93 - prefix?: React.ReactNode; 94 - suffix?: React.ReactNode; 95 - } 96 - 97 - function TreeItemContent({ children, prefix, suffix }: TreeItemContentProps) { 98 - const listBoxItemStyles = useListBoxItemStyles(); 99 - 100 - return ( 101 - <AriaTreeItemContent> 102 - {({ 103 - hasChildItems, 104 - selectionBehavior, 105 - selectionMode, 106 - allowsDragging, 107 - }) => ( 108 - <div {...stylex.props(listBoxItemStyles.inner, styles.itemInner)}> 109 - {allowsDragging && ( 110 - <div {...stylex.props(styles.dragButtonWrapper)}> 111 - <Button 112 - slot="drag" 113 - {...stylex.props(styles.dragButton, gray.border, gray.bgSubtle)} 114 - > 115 - <GripVertical size={18} /> 116 - </Button> 117 - </div> 118 - )} 119 - {selectionBehavior === "toggle" && selectionMode !== "none" && ( 120 - <Checkbox slot="selection" /> 121 - )} 122 - <div {...stylex.props(styles.spacer)} /> 123 - <Button 124 - slot="chevron" 125 - {...stylex.props( 126 - styles.chevron, 127 - gray.textDim, 128 - listBoxItemStyles.addon, 129 - !hasChildItems && styles.hidden, 130 - )} 131 - > 132 - <ChevronRight size={16} /> 133 - </Button> 134 - 135 - <div {...stylex.props(styles.content)}> 136 - {prefix !== null && ( 137 - <div {...stylex.props(listBoxItemStyles.addon, styles.addon)}> 138 - {prefix} 139 - </div> 140 - )} 141 - <div {...stylex.props(listBoxItemStyles.label)}>{children}</div> 142 - {suffix !== null && ( 143 - <div {...stylex.props(listBoxItemStyles.addon, styles.addon)}> 144 - {suffix} 145 - </div> 146 - )} 147 - </div> 148 - </div> 149 - )} 150 - </AriaTreeItemContent> 151 - ); 152 - } 153 - 154 - interface TreeItemProps<T extends object> 155 - extends 156 - Omit<AriaTreeItemProps<T>, "style" | "textValue" | "children">, 157 - Pick<TreeItemContentProps, "prefix" | "suffix"> { 158 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 159 - title: string; 160 - children?: React.ReactNode; 161 - } 162 - 163 - export function TreeItem<T extends object>({ 164 - style, 165 - title, 166 - prefix, 167 - suffix, 168 - ...props 169 - }: TreeItemProps<T>) { 170 - const listBoxItemStyles = useListBoxItemStyles(); 171 - 172 - return ( 173 - <AriaTreeItem 174 - textValue={title} 175 - {...props} 176 - data-react-aria-pressable 177 - {...stylex.props( 178 - listBoxItemStyles.wrapper, 179 - styles.wrapper, 180 - styles.itemInner, 181 - style, 182 - )} 183 - > 184 - <TreeItemContent prefix={prefix} suffix={suffix}> 185 - {title} 186 - </TreeItemContent> 187 - {props.children} 188 - </AriaTreeItem> 189 - ); 190 - } 191 - 192 - export interface TreeProps<T extends object> extends Omit< 193 - AriaTreeProps<T>, 194 - "children" | "style" 195 - > { 196 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 197 - children: React.ReactNode | ((item: T) => React.ReactNode); 198 - size?: Size; 199 - } 200 - 201 - export function Tree<T extends object>({ 202 - style, 203 - size: sizeProp, 204 - ...props 205 - }: TreeProps<T>) { 206 - const size = sizeProp || use(SizeContext); 207 - 208 - return ( 209 - <SizeContext value={size}> 210 - <AriaTree {...props} {...stylex.props(style)} /> 211 - </SizeContext> 212 - ); 213 - }
-7
apps/example/src/components/types.ts
··· 1 - export type Size = "sm" | "md" | "lg"; 2 - export type ButtonVariant = 3 - | "primary" 4 - | "secondary" 5 - | "tertiary" 6 - | "outline" 7 - | "critical";
-236
apps/example/src/components/typography/index.tsx
··· 1 - import * as stylex from "@stylexjs/stylex"; 2 - import { useMemo } from "react"; 3 - 4 - import { LinkContext } from "../link/link-context"; 5 - import { radius } from "../theme/radius.stylex"; 6 - import { gray } from "../theme/semantic-color.stylex"; 7 - import { spacing } from "../theme/spacing.stylex"; 8 - import { 9 - fontFamily, 10 - fontSize, 11 - lineHeight, 12 - typeramp, 13 - } from "../theme/typography.stylex"; 14 - 15 - const styles = stylex.create({ 16 - blockquote: { 17 - color: gray.textDim, 18 - fontFamily: fontFamily["serif"], 19 - borderLeftColor: gray.borderDim, 20 - borderLeftStyle: "solid", 21 - borderLeftWidth: 1, 22 - marginBottom: 0, 23 - marginLeft: spacing["2"], 24 - marginRight: 0, 25 - marginTop: 0, 26 - paddingLeft: spacing["4"], 27 - }, 28 - unorderedList: { 29 - margin: 0, 30 - gap: spacing["1"], 31 - display: "flex", 32 - flexDirection: "column", 33 - listStyleType: "disc", 34 - paddingLeft: spacing["8"], 35 - }, 36 - orderedList: { 37 - margin: 0, 38 - gap: spacing["1"], 39 - display: "flex", 40 - flexDirection: "column", 41 - listStyleType: "decimal", 42 - paddingLeft: spacing["8"], 43 - }, 44 - listItem: { 45 - fontFamily: fontFamily["sans"], 46 - fontSize: fontSize["base"], 47 - lineHeight: lineHeight["base"], 48 - paddingLeft: spacing["1"], 49 - }, 50 - inlineCode: { 51 - padding: spacing["1"], 52 - borderRadius: radius["sm"], 53 - fontSize: "0.9em", 54 - }, 55 - underline: { 56 - textDecorationLine: "underline", 57 - }, 58 - }); 59 - 60 - export interface Heading1Props extends Omit< 61 - React.ComponentProps<"h1">, 62 - "style" | "className" 63 - > { 64 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 65 - } 66 - 67 - export const Heading1 = ({ style, ...props }: Heading1Props) => { 68 - // eslint-disable-next-line jsx-a11y/heading-has-content 69 - return <h1 {...stylex.props(typeramp.heading1, style)} {...props} />; 70 - }; 71 - 72 - export interface Heading2Props extends Omit< 73 - React.ComponentProps<"h2">, 74 - "style" | "className" 75 - > { 76 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 77 - } 78 - 79 - export const Heading2 = ({ style, ...props }: Heading2Props) => { 80 - // eslint-disable-next-line jsx-a11y/heading-has-content 81 - return <h2 {...stylex.props(typeramp.heading2, style)} {...props} />; 82 - }; 83 - 84 - export interface Heading3Props extends Omit< 85 - React.ComponentProps<"h3">, 86 - "style" | "className" 87 - > { 88 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 89 - } 90 - 91 - export const Heading3 = ({ style, ...props }: Heading3Props) => { 92 - // eslint-disable-next-line jsx-a11y/heading-has-content 93 - return <h3 {...stylex.props(typeramp.heading3, style)} {...props} />; 94 - }; 95 - 96 - export interface Heading4Props extends Omit< 97 - React.ComponentProps<"h4">, 98 - "style" | "className" 99 - > { 100 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 101 - } 102 - 103 - export const Heading4 = ({ style, ...props }: Heading4Props) => { 104 - // eslint-disable-next-line jsx-a11y/heading-has-content 105 - return <h4 {...stylex.props(typeramp.heading4, style)} {...props} />; 106 - }; 107 - 108 - export interface BodyProps extends Omit< 109 - React.ComponentProps<"p">, 110 - "style" | "className" 111 - > { 112 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 113 - } 114 - 115 - export const Body = ({ style, ...props }: BodyProps) => { 116 - return <p {...stylex.props(typeramp.body, style)} {...props} />; 117 - }; 118 - 119 - export interface SmallBodyProps extends Omit< 120 - React.ComponentProps<"p">, 121 - "style" | "className" 122 - > { 123 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 124 - variant?: "default" | "secondary"; 125 - } 126 - 127 - export const SmallBody = ({ 128 - style, 129 - variant = "default", 130 - ...props 131 - }: SmallBodyProps) => { 132 - return ( 133 - <p 134 - {...stylex.props( 135 - typeramp.smallBody, 136 - variant === "secondary" && gray.textDim, 137 - style, 138 - )} 139 - {...props} 140 - /> 141 - ); 142 - }; 143 - 144 - interface SubLabelProps extends Omit< 145 - React.ComponentProps<"p">, 146 - "style" | "className" 147 - > { 148 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 149 - variant?: "default" | "secondary"; 150 - } 151 - 152 - export const SubLabel = ({ 153 - style, 154 - variant = "default", 155 - ...props 156 - }: SubLabelProps) => { 157 - const contextValue = useMemo( 158 - () => ({ 159 - style: [variant === "secondary" && gray.textDim, styles.underline], 160 - }), 161 - [variant], 162 - ); 163 - 164 - return ( 165 - <LinkContext value={contextValue}> 166 - <p 167 - {...stylex.props( 168 - typeramp.sublabel, 169 - variant === "secondary" && gray.textDim, 170 - style, 171 - )} 172 - {...props} 173 - /> 174 - </LinkContext> 175 - ); 176 - }; 177 - 178 - export interface BlockquoteProps extends Omit< 179 - React.ComponentProps<"blockquote">, 180 - "style" | "className" 181 - > { 182 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 183 - } 184 - 185 - export const Blockquote = ({ style, ...props }: BlockquoteProps) => { 186 - return <blockquote {...stylex.props(styles.blockquote, style)} {...props} />; 187 - }; 188 - 189 - export interface UnorderedListProps extends Omit< 190 - React.ComponentProps<"ul">, 191 - "style" | "className" 192 - > { 193 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 194 - } 195 - 196 - export const UnorderedList = ({ style, ...props }: UnorderedListProps) => { 197 - return <ul {...stylex.props(styles.unorderedList, style)} {...props} />; 198 - }; 199 - 200 - export interface OrderedListProps extends Omit< 201 - React.ComponentProps<"ol">, 202 - "style" | "className" 203 - > { 204 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 205 - } 206 - 207 - export const OrderedList = ({ style, ...props }: OrderedListProps) => { 208 - return <ol {...stylex.props(styles.orderedList, style)} {...props} />; 209 - }; 210 - 211 - export interface ListItemProps extends Omit< 212 - React.ComponentProps<"li">, 213 - "style" | "className" 214 - > { 215 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 216 - } 217 - 218 - export const ListItem = ({ style, ...props }: ListItemProps) => { 219 - return <li {...stylex.props(styles.listItem, style)} {...props} />; 220 - }; 221 - 222 - export interface InlineCodeProps extends Omit< 223 - React.ComponentProps<"code">, 224 - "style" | "className" 225 - > { 226 - style?: stylex.StyleXStyles | stylex.StyleXStyles[]; 227 - } 228 - 229 - export const InlineCode = ({ style, ...props }: InlineCodeProps) => { 230 - return ( 231 - <code 232 - {...stylex.props(styles.inlineCode, gray.bgSecondary, style)} 233 - {...props} 234 - /> 235 - ); 236 - };
-19
apps/example/src/pages.gen.ts
··· 1 - // deno-fmt-ignore-file 2 - // biome-ignore format: generated types do not need formatting 3 - // prettier-ignore 4 - import type { GetConfigResponse, PathsForPages } from 'waku/router'; 5 - 6 - 7 - // prettier-ignore 8 - type Page = 9 - | { path: '/'; render: 'dynamic' }; 10 - 11 - // prettier-ignore 12 - declare module 'waku/router' { 13 - interface RouteConfig { 14 - paths: PathsForPages<Page>; 15 - } 16 - interface CreatePagesConfig { 17 - pages: Page; 18 - } 19 - }
-32
apps/example/src/pages/_layout.tsx
··· 1 - import type { ReactNode } from "react"; 2 - 3 - type RootLayoutProps = { children: ReactNode }; 4 - 5 - export default async function RootLayout({ children }: RootLayoutProps) { 6 - const data = await getData(); 7 - 8 - return ( 9 - <div> 10 - <meta name="description" content={data.description} /> 11 - <link rel="icon" type="image/png" href={data.icon} /> 12 - <style>{"body { margin: 0; }"}</style> 13 - <main>{children}</main> 14 - </div> 15 - ); 16 - } 17 - 18 - const getData = async () => { 19 - const data = { 20 - description: "An internet website!", 21 - icon: "/images/favicon.png", 22 - }; 23 - 24 - return data; 25 - }; 26 - 27 - // oxlint-disable-next-line react/only-export-components 28 - export const getConfig = async () => { 29 - return { 30 - render: "static", 31 - } as const; 32 - };
-5
apps/example/src/pages/index.tsx
··· 1 - import { KitchenSink } from "../components/KitchenSink"; 2 - 3 - export default function HomePage() { 4 - return <KitchenSink />; 5 - }
-16
apps/example/tsconfig.json
··· 1 - { 2 - "compilerOptions": { 3 - "strict": true, 4 - "target": "esnext", 5 - "noEmit": true, 6 - "isolatedModules": true, 7 - "moduleDetection": "force", 8 - "downlevelIteration": true, 9 - "esModuleInterop": true, 10 - "module": "esnext", 11 - "moduleResolution": "bundler", 12 - "skipLibCheck": true, 13 - "noUncheckedIndexedAccess": true, 14 - "jsx": "react-jsx" 15 - } 16 - }
-14
apps/example/waku.config.ts
··· 1 - import stylexPlugin from "unplugin-stylex/vite"; 2 - import { defineConfig } from "waku/config"; 3 - 4 - export default defineConfig({ 5 - vite: { 6 - plugins: [ 7 - stylexPlugin({ 8 - stylex: { 9 - debug: false, 10 - }, 11 - }), 12 - ], 13 - }, 14 - });