qstd 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -88,11 +88,19 @@ import { defineConfig } from "@pandacss/dev";
88
88
  import qstdPreset from "qstd/preset";
89
89
 
90
90
  export default defineConfig({
91
+ preflight: true,
92
+
91
93
  // IMPORTANT: Include base preset to get default colors (neutral, red, blue, etc.)
92
94
  presets: ["@pandacss/dev/presets", qstdPreset],
93
95
 
94
96
  include: ["./src/**/*.{ts,tsx}"],
95
97
 
98
+ outdir: "styled-system",
99
+
100
+ // REQUIRED: Enables Panda CSS to detect props on the Block component
101
+ // Without this, styles like bg="red" won't generate CSS utilities
102
+ jsxFramework: "react",
103
+
96
104
  theme: {
97
105
  extend: {
98
106
  // Your custom theme
@@ -101,6 +109,8 @@ export default defineConfig({
101
109
  });
102
110
  ```
103
111
 
112
+ **⚠️ Critical:** The `jsxFramework: "react"` setting is **required** for the Block component to work correctly. Without it, Panda CSS cannot detect style props like `bg="red"` on the Block component, and no CSS utilities will be generated.
113
+
104
114
  ## Global Types
105
115
 
106
116
  When you install qstd, these types become **globally available** (no import needed):
@@ -121,6 +131,764 @@ When you install qstd, these types become **globally available** (no import need
121
131
  ## Documentation
122
132
 
123
133
  See [SUMMARY.md](./SUMMARY.md) for complete package contents and [QSTD_PACKAGE_PRD.md](./QSTD_PACKAGE_PRD.md) for full specification.
134
+ For the interactive development playground showcasing Block variants, see [playground/README.md](./playground/README.md).
135
+
136
+ ## Block Component Documentation
137
+
138
+ The `Block` component is a universal building block that replaces most HTML elements with an intelligent, prop-driven API powered by PandaCSS. It supports semantic HTML, grid/flex layouts, compound components, and extensive styling utilities.
139
+
140
+ ### Quick Start
141
+
142
+ ```tsx
143
+ import Block from "qstd/react";
144
+
145
+ // Simplest text
146
+ <Block>Hello World</Block>
147
+
148
+ // Text with styling
149
+ <Block is="txt" fontSize="lg" color="blue.500">
150
+ Styled text
151
+ </Block>
152
+ ```
153
+
154
+ ### Core Concepts
155
+
156
+ #### The `is` Prop (Component Type)
157
+
158
+ The `is` prop tells Block what kind of component to render:
159
+
160
+ ```tsx
161
+ // Text elements
162
+ <Block is="txt">Default paragraph</Block>
163
+ <Block is="txt" as="h1">Heading 1</Block>
164
+ <Block is="txt" as="span">Inline text</Block>
165
+
166
+ // Interactive elements
167
+ <Block is="btn" onClick={handleClick}>Button</Block>
168
+ <Block is="link" onClick={navigate}>Link-styled button</Block>
169
+ <Block is="checkbox" checked={isChecked} onChecked={setIsChecked}>
170
+ Accept terms
171
+ </Block>
172
+
173
+ // Inputs
174
+ <Block is="input" placeholder="Enter text" />
175
+ <Block is="textarea" placeholder="Enter description" />
176
+
177
+ // Complex components
178
+ <Block is="progress" value={50} max={100} />
179
+ <Block is="drawer" open={isOpen} onClose={handleClose}>
180
+ Drawer content
181
+ </Block>
182
+ <Block is="radio" options={radioOptions} onChange={handleChange} />
183
+ <Block is="accordion">Accordion content</Block>
184
+ <Block is="menu" trigger={<Block is="btn">Menu</Block>}>
185
+ Menu items
186
+ </Block>
187
+
188
+ // Semantic elements
189
+ <Block is="seo" as="nav">Navigation</Block>
190
+ <Block is="seo" as="main">Main content</Block>
191
+ <Block is="seo" as="article">Article</Block>
192
+ <Block is="list" as="ul">Unordered list</Block>
193
+ <Block is="list" as="li">List item</Block>
194
+ <Block is="form" as="label">Label</Block>
195
+ ```
196
+
197
+ #### The `as` Prop (Semantic HTML)
198
+
199
+ The `as` prop lets you control the underlying HTML element for SEO and accessibility:
200
+
201
+ ```tsx
202
+ // Text as different heading levels
203
+ <Block is="txt" as="h1" fontSize="2xl">Page Title</Block>
204
+ <Block is="txt" as="h2" fontSize="xl">Section Title</Block>
205
+ <Block is="txt" as="p">Paragraph</Block>
206
+ <Block is="txt" as="span">Inline text</Block>
207
+
208
+ // Semantic structure
209
+ <Block is="seo" as="header">Site header</Block>
210
+ <Block is="seo" as="footer">Site footer</Block>
211
+ <Block is="seo" as="nav">Navigation</Block>
212
+ <Block is="seo" as="main">Main content</Block>
213
+ <Block is="seo" as="aside">Sidebar</Block>
214
+ <Block is="seo" as="section">Section</Block>
215
+
216
+ // Lists
217
+ <Block is="list" as="ul">
218
+ <Block is="list" as="li">Item 1</Block>
219
+ <Block is="list" as="li">Item 2</Block>
220
+ </Block>
221
+
222
+ // Forms
223
+ <Block is="form" as="form" onSubmit={handleSubmit}>
224
+ <Block is="form" as="label">Email</Block>
225
+ <Block is="input" type="email" />
226
+ </Block>
227
+ ```
228
+
229
+ ### Layout with Grid & Flex
230
+
231
+ #### Boolean Layout Props
232
+
233
+ ```tsx
234
+ // Flex layout
235
+ <Block flex>Flex container</Block>
236
+ <Block flex="wrap">Flex with wrapping</Block>
237
+
238
+ // Grid layout
239
+ <Block grid>Grid container</Block>
240
+
241
+ // Centering
242
+ <Block center>Centered content</Block>
243
+
244
+ // Positioning
245
+ <Block relative>Relative position</Block>
246
+ <Block absolute>Absolute position</Block>
247
+ <Block fixed>Fixed position</Block>
248
+ <Block sticky>Sticky position</Block>
249
+ ```
250
+
251
+ #### Grid `cols` Prop (Flexible Column Syntax)
252
+
253
+ The `cols` prop provides a powerful shorthand for grid columns:
254
+
255
+ ```tsx
256
+ // Basic columns - numbers become fr units
257
+ <Block grid cols="1 1 1">Three equal columns</Block>
258
+ <Block grid cols="2 1 1">2fr 1fr 1fr columns</Block>
259
+
260
+ // Max-content with 'm'
261
+ <Block grid cols="m 1 1 m 1">
262
+ {/* max-content 1fr 1fr max-content 1fr */}
263
+ </Block>
264
+
265
+ // Alignment + columns
266
+ <Block grid cols="center 1 1 1">
267
+ {/* Centers columns: alignContent + alignItems: center */}
268
+ </Block>
269
+ <Block grid cols="start 1 2 1">
270
+ {/* Aligns to start */}
271
+ </Block>
272
+
273
+ // Column gap with slash
274
+ <Block grid cols="1 1 1 / 10">
275
+ {/* 10px column gap */}
276
+ </Block>
277
+
278
+ // Complete example
279
+ <Block grid cols="center 1 1 m 1 / 10">
280
+ {/* alignContent: center, alignItems: center */}
281
+ {/* gridTemplateColumns: 1fr 1fr max-content 1fr */}
282
+ {/* columnGap: 10px */}
283
+ </Block>
284
+
285
+ // Just alignment
286
+ <Block grid cols="center">
287
+ {/* Only centers, no column template */}
288
+ </Block>
289
+ ```
290
+
291
+ #### Grid `rows` Prop (Flexible Row Syntax)
292
+
293
+ The `rows` prop mirrors `cols` but for grid rows:
294
+
295
+ ```tsx
296
+ // Basic rows
297
+ <Block grid rows="1 1 1">Three equal rows</Block>
298
+ <Block grid rows="m m 1">
299
+ {/* max-content max-content 1fr */}
300
+ </Block>
301
+
302
+ // Alignment + rows
303
+ <Block grid rows="between m m m">
304
+ {/* justifyContent: space-between, justifyItems: space-between */}
305
+ {/* gridTemplateRows: max-content max-content max-content */}
306
+ </Block>
307
+ <Block grid rows="start 1 2 1">Start-aligned rows</Block>
308
+ <Block grid rows="end 1 1 1">End-aligned rows</Block>
309
+
310
+ // Row gap with slash
311
+ <Block grid rows="1 1 / 8">
312
+ {/* 8px row gap */}
313
+ </Block>
314
+
315
+ // Complete example
316
+ <Block grid rows="between m m m / 10">
317
+ {/* justifyContent: space-between, justifyItems: space-between */}
318
+ {/* gridTemplateRows: max-content max-content max-content */}
319
+ {/* rowGap: 10px */}
320
+ </Block>
321
+ ```
322
+
323
+ #### Real-World Layout Examples
324
+
325
+ ```tsx
326
+ // Chat page header
327
+ <Block
328
+ grid
329
+ rows="m 1 m"
330
+ h="100dvh"
331
+ w
332
+ maxW="700px"
333
+ mx="auto"
334
+ overflow="hidden"
335
+ px={{ base: 1, sm: 0 }}
336
+ pb={{ base: 1, sm: 4 }}
337
+ >
338
+ <Block rows="between" my={2}>
339
+ {/* Header content */}
340
+ </Block>
341
+ {/* Main content */}
342
+ {/* Footer/Chatbox */}
343
+ </Block>
344
+
345
+ // Playground sidebar
346
+ <Block grid cols="250px 1fr" h="100vh" overflow="hidden">
347
+ <Block
348
+ bg={{ base: "neutral.50", _dark: "neutral.900" }}
349
+ borderRight="1px solid"
350
+ borderColor={{ base: "neutral.200", _dark: "neutral.700" }}
351
+ p={4}
352
+ rowG={4}
353
+ >
354
+ {/* Sidebar */}
355
+ </Block>
356
+ <Block overflow="auto" position="relative">
357
+ {/* Main content */}
358
+ </Block>
359
+ </Block>
360
+
361
+ // Icon + text flex layout
362
+ <Block flex cols="center / 4">
363
+ <Icon icon={TbMessage2} fontSize="sm" />
364
+ <Block is="txt">{messageCount}</Block>
365
+ </Block>
366
+ ```
367
+
368
+ ### Debug Utilities
369
+
370
+ The `debug` prop adds visual borders for layout debugging:
371
+
372
+ ```tsx
373
+ // Default red border
374
+ <Block debug>Debug border</Block>
375
+
376
+ // Color only
377
+ <Block debug="blue">Blue border</Block>
378
+ <Block debug="green">Green border</Block>
379
+
380
+ // Width + color
381
+ <Block debug="2px red">2px red border</Block>
382
+ <Block debug="10px orange">10px orange border</Block>
383
+
384
+ // Style + color
385
+ <Block debug="dashed blue">Dashed blue border</Block>
386
+ <Block debug="dotted green">Dotted green border</Block>
387
+ <Block debug="solid red">Solid red border</Block>
388
+
389
+ // Full control
390
+ <Block debug="3px dotted orange">3px dotted orange</Block>
391
+ <Block debug="2px dashed">2px dashed red (default color)</Block>
392
+
393
+ // Panda tokens work too
394
+ <Block debug="blue.500">Uses Panda color token</Block>
395
+ <Block debug="text-primary">Uses semantic token</Block>
396
+ ```
397
+
398
+ ### Compound Components
399
+
400
+ Block includes several compound components accessible via namespace:
401
+
402
+ #### Progress
403
+
404
+ ```tsx
405
+ // Simple progress
406
+ <Block is="progress" value={50} max={100} w="200px" h={6} />
407
+
408
+ // Custom styled progress
409
+ <Block is="progress" value={progress} max={100} w="200px" h={6}>
410
+ <Block.Progress.TrackBg
411
+ bg={{ base: "red.200", _dark: "neutral.700" }}
412
+ />
413
+ <Block.Progress.TrackFill
414
+ bg={{
415
+ base: "blue.500",
416
+ _dark: progress > 60 ? "green.400" : "red.400",
417
+ }}
418
+ />
419
+ </Block>
420
+ ```
421
+
422
+ #### Drawer
423
+
424
+ ```tsx
425
+ <Block is="btn" onClick={() => setOpen(true)}>
426
+ Open Drawer
427
+ </Block>
428
+
429
+ <Block is="drawer" open={isOpen} onClose={() => setOpen(false)}>
430
+ <Block.Drawer.CloseButton onClick={() => setOpen(false)} />
431
+ <Block p={8}>
432
+ Drawer content here
433
+ </Block>
434
+ </Block>
435
+ ```
436
+
437
+ #### Radio
438
+
439
+ ```tsx
440
+ // Default radio
441
+ <Block
442
+ is="radio"
443
+ defaultValue="1"
444
+ options={[
445
+ { label: "Option 1", value: "1" },
446
+ { label: "Option 2", value: "2" },
447
+ { label: "Option 3 (disabled)", value: "3", disabled: true },
448
+ ]}
449
+ onChange={(value) => console.log(value)}
450
+ _radioSelected={{ _radioCircleOuter: { borderColor: "blue.400" } }}
451
+ />
452
+
453
+ // Custom rendered radio
454
+ <Block
455
+ is="radio"
456
+ defaultValue="2"
457
+ options={options}
458
+ _radioCircleOuter={{ size: 12, borderColor: "neutral.500" }}
459
+ _radioCircleInner={{ size: 4 }}
460
+ _radioSelected={{ _radioCircleOuter: { borderColor: "violet.400" } }}
461
+ _radioDisabled={{ _radioCircleOuter: { borderColor: "neutral.400" } }}
462
+ renderOption={(option) => (
463
+ <Block.Radio.Item
464
+ cols="/ 10"
465
+ value={option.value}
466
+ disabled={option.disabled}
467
+ >
468
+ {option.label}
469
+ </Block.Radio.Item>
470
+ )}
471
+ onChange={(value) => console.log(value)}
472
+ />
473
+ ```
474
+
475
+ #### Switch
476
+
477
+ ```tsx
478
+ <Block is="switch" checked={isOn} onChange={setIsOn}>
479
+ <Block.Switch.Track
480
+ bg={{
481
+ base: isOn ? "blue.500!" : "neutral.300",
482
+ _dark: isOn ? "blue.500!" : "neutral.700",
483
+ }}
484
+ />
485
+ <Block.Switch.Thumb bg={{ base: "neutral.100", _dark: "neutral.900" }} />
486
+ </Block>
487
+ ```
488
+
489
+ #### Accordion
490
+
491
+ ```tsx
492
+ <Block is="accordion">
493
+ <Block.Accordion.Item title="Accordion Item 1" cols="/ 10">
494
+ Content for item 1
495
+ </Block.Accordion.Item>
496
+ <Block.Accordion.Item
497
+ title={
498
+ <Block is="txt" color="text-primary">
499
+ Custom Title
500
+ </Block>
501
+ }
502
+ cols="/ 10"
503
+ >
504
+ Content for item 2
505
+ </Block.Accordion.Item>
506
+ </Block>
507
+ ```
508
+
509
+ #### Input
510
+
511
+ ```tsx
512
+ // Simple input
513
+ <Block is="input" placeholder="Search" value={value} onChange={handleChange} />
514
+
515
+ // Input with icon and label
516
+ <Block
517
+ is="input"
518
+ placeholder="Search tests"
519
+ pl="28px"
520
+ value={searchTerm}
521
+ onChange={(e) => setSearchTerm(e.target.value)}
522
+ >
523
+ <Block.Input.LeftIcon
524
+ icon="search"
525
+ left="8px"
526
+ fontSize="xs"
527
+ color="text-secondary"
528
+ />
529
+ </Block>
530
+
531
+ // Input with label
532
+ <Block is="input" placeholder="Email">
533
+ <Block.Input.Label>Email Address</Block.Input.Label>
534
+ </Block>
535
+ ```
536
+
537
+ #### Textarea
538
+
539
+ ```tsx
540
+ <Block
541
+ is="textarea"
542
+ placeholder="Type something..."
543
+ pl="28px"
544
+ error="This is an error"
545
+ minW={200}
546
+ minRows={2}
547
+ maxRows={8}
548
+ transition=".2s height ease-out"
549
+ value={txtarea}
550
+ onChange={(e) => setTxtareaVal(e.target.value)}
551
+ >
552
+ <Block.Textarea.Label>Description</Block.Textarea.Label>
553
+ </Block>
554
+ ```
555
+
556
+ #### Menu
557
+
558
+ ```tsx
559
+ <Block is="menu" variant="click" trigger={<Block is="btn">Open Menu</Block>}>
560
+ <Block.Menu.Container grid rows="/ 4" px={4} py={2} borderRadius="8">
561
+ <Block is="txt" color="text-primary">
562
+ Menu Item 1
563
+ </Block>
564
+ <Block is="txt" color="text-primary">
565
+ Menu Item 2
566
+ </Block>
567
+ <Block is="txt" color="text-primary">
568
+ Menu Item 3
569
+ </Block>
570
+ </Block.Menu.Container>
571
+ </Block>
572
+ ```
573
+
574
+ #### Tooltip
575
+
576
+ ```tsx
577
+ // Simple tooltip
578
+ <Block is="btn" tooltip="This is a tooltip">
579
+ Hover me
580
+ </Block>
581
+
582
+ // Custom tooltip
583
+ <Block
584
+ is="btn"
585
+ tooltip={
586
+ <Block.Tooltip.Container
587
+ bg="blue.900"
588
+ color={{ base: "blue.400", _dark: "red.400" }}
589
+ >
590
+ Custom styled tooltip!
591
+ </Block.Tooltip.Container>
592
+ }
593
+ >
594
+ Hover for custom tooltip
595
+ </Block>
596
+ ```
597
+
598
+ ### Common Utility Props
599
+
600
+ ```tsx
601
+ // Sizing
602
+ <Block w>Full width (100%)</Block>
603
+ <Block w={200}>200px width</Block>
604
+ <Block h>Full height (100%)</Block>
605
+ <Block size={40}>40px × 40px</Block>
606
+
607
+ // Spacing
608
+ <Block p={4}>Padding 4</Block>
609
+ <Block px={2} py={1}>Padding x/y</Block>
610
+ <Block m={2}>Margin 2</Block>
611
+ <Block mx="auto">Centered horizontally</Block>
612
+ <Block gap={4}>Gap for flex/grid children</Block>
613
+ <Block rowG={3}>Row gap (grid)</Block>
614
+ <Block colG={3}>Column gap (grid)</Block>
615
+
616
+ // Borders
617
+ <Block br={4}>Border radius 4px</Block>
618
+ <Block rounded>Fully rounded (9999px)</Block>
619
+ <Block border="1px solid" borderColor="neutral.300">
620
+ Custom border
621
+ </Block>
622
+
623
+ // Colors
624
+ <Block bg="blue.500">Background color</Block>
625
+ <Block color="text-primary">Text color</Block>
626
+
627
+ // Typography
628
+ <Block fontSize="xl">Extra large text</Block>
629
+ <Block fontWeight="bold">Bold text</Block>
630
+ <Block letterSpacing={0.2}>Letter spacing</Block>
631
+
632
+ // Display
633
+ <Block overflow="hidden">Hidden overflow</Block>
634
+ <Block overflowY="auto">Vertical scroll</Block>
635
+ <Block opacity={0.5}>50% opacity</Block>
636
+
637
+ // Positioning
638
+ <Block zIndex={10}>Z-index 10</Block>
639
+ <Block top={0} left={0}>Positioned</Block>
640
+
641
+ // Interactions
642
+ <Block pointer>Cursor pointer</Block>
643
+ <Block cursor="not-allowed">Disabled cursor</Block>
644
+ ```
645
+
646
+ ### Icon Support
647
+
648
+ ```tsx
649
+ // Standalone icon
650
+ <Block icon="check-circle" color="green.500" />
651
+
652
+ // Icon with text
653
+ <Block is="btn" icon="search" fontSize="sm">
654
+ Search
655
+ </Block>
656
+
657
+ // Start and end icons
658
+ <Block is="btn" startIcon="arrow-left" endIcon="arrow-right">
659
+ Navigate
660
+ </Block>
661
+
662
+ // Loading state
663
+ <Block is="btn" isLoading loadingIcon="oval">
664
+ Loading
665
+ </Block>
666
+
667
+ // Custom loading styles
668
+ <Block
669
+ is="btn"
670
+ isLoading
671
+ _loading={{ strokeColor: "blue.500", opacity: 0.8 }}
672
+ >
673
+ Processing
674
+ </Block>
675
+ ```
676
+
677
+ ### Special Features
678
+
679
+ #### Skeleton Loading
680
+
681
+ ```tsx
682
+ // Circle skeleton
683
+ <Block is="skeleton" as="circle" />
684
+
685
+ // Block skeleton
686
+ <Block is="skeleton" as="block" h={8} br={4} />
687
+ <Block is="skeleton" as="block" h={8} br={4} w="85%" />
688
+
689
+ // Skeleton layout example
690
+ <Block grid rows="/ 18" w>
691
+ <Block flex cols="center / 24">
692
+ <Block is="skeleton" as="circle" />
693
+ <Block grid rows="/ 18" w>
694
+ <Block is="skeleton" as="block" h={8} br={4} />
695
+ <Block is="skeleton" as="block" h={8} br={4} />
696
+ </Block>
697
+ </Block>
698
+ <Block is="skeleton" as="block" h={8} br={4} w="85%" />
699
+ </Block>
700
+ ```
701
+
702
+ #### Horizontal Rule
703
+
704
+ ```tsx
705
+ <Block is="hr" />
706
+ <Block is="hr" color="blue.500" />
707
+ ```
708
+
709
+ #### File Picker
710
+
711
+ ```tsx
712
+ <Block is="btn" filepicker multiple onChange={(files) => handleFiles(files)}>
713
+ Choose Files
714
+ </Block>
715
+ ```
716
+
717
+ #### Portal Rendering
718
+
719
+ ```tsx
720
+ <Block portal>Rendered in portal</Block>
721
+ <Block portal portalContainer={customContainer}>
722
+ Custom portal target
723
+ </Block>
724
+ ```
725
+
726
+ ### Kitchen Sink Example
727
+
728
+ ```tsx
729
+ // Complex button with all features
730
+ <Block
731
+ is="btn"
732
+ grid
733
+ cols="m m / 8"
734
+ rows="center"
735
+ px={4}
736
+ py={2}
737
+ bg={{ base: "blue.500", _dark: "blue.600" }}
738
+ color="white"
739
+ rounded
740
+ icon="check-circle"
741
+ isLoading={isProcessing}
742
+ disabled={!isValid}
743
+ loadingIcon="spinner"
744
+ _loading={{ strokeColor: "white", opacity: 0.6 }}
745
+ _hover={{ bg: "blue.600" }}
746
+ onClick={handleSubmit}
747
+ whileTap={{ scale: 0.95 }}
748
+ transition={{ duration: 0.2 }}
749
+ tooltip="Submit form"
750
+ debug="dashed blue"
751
+ >
752
+ Submit Form
753
+ </Block>
754
+
755
+ // Complex layout composition
756
+ <Block
757
+ grid
758
+ rows="m 1 m"
759
+ h="100vh"
760
+ w
761
+ maxW="1200px"
762
+ mx="auto"
763
+ bg={{ base: "neutral.50", _dark: "neutral.900" }}
764
+ borderRadius={12}
765
+ p={6}
766
+ gap={4}
767
+ >
768
+ {/* Header */}
769
+ <Block
770
+ is="seo"
771
+ as="header"
772
+ grid
773
+ cols="1 m / 12"
774
+ alignI="center"
775
+ borderBottom="1px solid"
776
+ borderColor="neutral.200"
777
+ pb={4}
778
+ >
779
+ <Block is="txt" as="h1" fontSize="2xl" fontWeight="bold">
780
+ Dashboard
781
+ </Block>
782
+ <Block is="btn" icon="settings" variant="ghost">
783
+ Settings
784
+ </Block>
785
+ </Block>
786
+
787
+ {/* Main Content */}
788
+ <Block
789
+ is="seo"
790
+ as="main"
791
+ grid
792
+ rows="/ 24"
793
+ overflow="auto"
794
+ >
795
+ <Block
796
+ grid
797
+ cols="1 1 1 / 16"
798
+ rows="/ 16"
799
+ bg="white"
800
+ br={8}
801
+ p={4}
802
+ debug="neutral.200"
803
+ >
804
+ <Block
805
+ is="progress"
806
+ value={progress}
807
+ max={100}
808
+ h={6}
809
+ >
810
+ <Block.Progress.TrackFill bg="green.500" />
811
+ </Block>
812
+ {/* More content */}
813
+ </Block>
814
+ </Block>
815
+
816
+ {/* Footer */}
817
+ <Block
818
+ is="seo"
819
+ as="footer"
820
+ flex
821
+ cols="center / 8"
822
+ borderTop="1px solid"
823
+ borderColor="neutral.200"
824
+ pt={4}
825
+ >
826
+ <Block is="txt" fontSize="xs" color="text-secondary">
827
+ © 2025 Your Company
828
+ </Block>
829
+ </Block>
830
+ </Block>
831
+ ```
832
+
833
+ ### Responsive Design
834
+
835
+ All props support Panda's responsive syntax:
836
+
837
+ ```tsx
838
+ <Block
839
+ grid
840
+ cols={{ base: "1", md: "1 1", lg: "1 1 1" }}
841
+ gap={{ base: 4, md: 6, lg: 8 }}
842
+ p={{ base: 2, sm: 4, md: 6 }}
843
+ fontSize={{ base: "sm", md: "md", lg: "lg" }}
844
+ >
845
+ Responsive content
846
+ </Block>
847
+ ```
848
+
849
+ ### Theme Awareness
850
+
851
+ Block automatically supports light/dark themes:
852
+
853
+ ```tsx
854
+ <Block
855
+ bg={{ base: "white", _dark: "neutral.900" }}
856
+ color={{ base: "neutral.900", _dark: "neutral.100" }}
857
+ borderColor={{ base: "neutral.200", _dark: "neutral.700" }}
858
+ >
859
+ Theme-aware content
860
+ </Block>
861
+ ```
862
+
863
+ ### TypeScript Support
864
+
865
+ Block is fully typed with TypeScript:
866
+
867
+ ```tsx
868
+ // Type-safe is/as combinations
869
+ <Block is="txt" as="h1">Title</Block> // ✅
870
+ <Block is="list" as="ul">List</Block> // ✅
871
+ <Block is="seo" as="nav">Nav</Block> // ✅
872
+
873
+ // Compile-time errors for invalid combinations
874
+ <Block is="txt" as="ul">Invalid</Block> // ❌ Error
875
+ <Block is="list">Missing as</Block> // ❌ Error
876
+
877
+ // Proper event typing
878
+ <Block is="btn" onClick={(e: React.MouseEvent) => {}}>
879
+ Typed events
880
+ </Block>
881
+ ```
882
+
883
+ ### Best Practices
884
+
885
+ 1. **Use semantic HTML**: Always provide the `as` prop for proper SEO and accessibility
886
+ 2. **Prefer grid/flex**: Use the boolean `grid` and `flex` props over manual CSS
887
+ 3. **Leverage cols/rows**: The shorthand syntax is more readable than verbose gridTemplateColumns
888
+ 4. **Debug visually**: Use `debug` prop during development to understand layouts
889
+ 5. **Compound components**: Use Block compound components instead of mixing component types
890
+ 6. **Responsive by default**: Always consider mobile-first responsive design
891
+ 7. **Type safety**: Let TypeScript guide you to correct `is`/`as` combinations
124
892
 
125
893
  ## License
126
894
 
@@ -4,7 +4,27 @@
4
4
  var preset = {
5
5
  name: "qstd-preset",
6
6
  globalCss: {
7
- ":root": { colorScheme: "light dark" },
7
+ ":root": {
8
+ /**
9
+ * Default UA surfaces (forms, scrollbars, etc.) to light mode so
10
+ * projects that do not opt into dark mode still get consistent styling.
11
+ */
12
+ colorScheme: "light"
13
+ },
14
+ "html[data-theme=light]": {
15
+ /**
16
+ * Keep the UA elements in sync with Panda's light theme tokens whenever
17
+ * a consumer sets data-theme="light".
18
+ */
19
+ colorScheme: "light"
20
+ },
21
+ "html[data-theme=dark]": {
22
+ /**
23
+ * Propagate the dark theme toggle down to the browser chrome so native
24
+ * controls respect the chosen theme.
25
+ */
26
+ colorScheme: "dark"
27
+ },
8
28
  html: {
9
29
  fontSize: 16,
10
30
  lineHeight: 1.5,
@@ -2,7 +2,27 @@
2
2
  var preset = {
3
3
  name: "qstd-preset",
4
4
  globalCss: {
5
- ":root": { colorScheme: "light dark" },
5
+ ":root": {
6
+ /**
7
+ * Default UA surfaces (forms, scrollbars, etc.) to light mode so
8
+ * projects that do not opt into dark mode still get consistent styling.
9
+ */
10
+ colorScheme: "light"
11
+ },
12
+ "html[data-theme=light]": {
13
+ /**
14
+ * Keep the UA elements in sync with Panda's light theme tokens whenever
15
+ * a consumer sets data-theme="light".
16
+ */
17
+ colorScheme: "light"
18
+ },
19
+ "html[data-theme=dark]": {
20
+ /**
21
+ * Propagate the dark theme toggle down to the browser chrome so native
22
+ * controls respect the chosen theme.
23
+ */
24
+ colorScheme: "dark"
25
+ },
6
26
  html: {
7
27
  fontSize: 16,
8
28
  lineHeight: 1.5,
@@ -205,7 +205,13 @@
205
205
  @layer base {
206
206
  :root {
207
207
  --made-with-panda: "\1f43c";
208
- color-scheme: light dark;
208
+ }
209
+ :root,
210
+ html[data-theme=light] {
211
+ color-scheme: light;
212
+ }
213
+ html[data-theme=dark] {
214
+ color-scheme: dark;
209
215
  }
210
216
  html {
211
217
  font-size: 16px;
@@ -20956,7 +20956,7 @@ declare function RightSide(props: BaseBlockProps & {
20956
20956
  declare namespace RightSide {
20957
20957
  var displayName: string;
20958
20958
  }
20959
- declare function Label(props: InputBlockProps & LabelProps): react_jsx_runtime.JSX.Element;
20959
+ declare function Label(props: Omit<InputBlockProps, "is"> & LabelProps): react_jsx_runtime.JSX.Element;
20960
20960
  declare namespace Label {
20961
20961
  var displayName: string;
20962
20962
  }
@@ -20956,7 +20956,7 @@ declare function RightSide(props: BaseBlockProps & {
20956
20956
  declare namespace RightSide {
20957
20957
  var displayName: string;
20958
20958
  }
20959
- declare function Label(props: InputBlockProps & LabelProps): react_jsx_runtime.JSX.Element;
20959
+ declare function Label(props: Omit<InputBlockProps, "is"> & LabelProps): react_jsx_runtime.JSX.Element;
20960
20960
  declare namespace Label {
20961
20961
  var displayName: string;
20962
20962
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qstd",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Standard Block component and utilities library with Panda CSS",
5
5
  "author": "malin1",
6
6
  "license": "MIT",
@@ -41,6 +41,21 @@
41
41
  "sideEffects": [
42
42
  "dist/react/index.css"
43
43
  ],
44
+ "scripts": {
45
+ "build": "panda codegen && panda cssgen && tsup && node scripts/inject-css-import.js",
46
+ "dev": "tsup --watch",
47
+ "prepublishOnly": "pnpm build",
48
+ "test": "vitest run",
49
+ "test:watch": "vitest",
50
+ "test:all": "pnpx tsx tests/test-all.ts",
51
+ "test:block": "node tests/test-block.tsx",
52
+ "test:playground": "node tests/playground-e2e.mjs",
53
+ "typecheck": "tsc --noEmit",
54
+ "typecheck:perf": "tsc --noEmit --extendedDiagnostics",
55
+ "typecheck:trace": "tsc --noEmit --generateTrace ./performance/ts-trace",
56
+ "analyze:tsserver": "bash performance/analyze-tsserver.sh",
57
+ "lint": "eslint src --ext ts,tsx"
58
+ },
44
59
  "peerDependencies": {
45
60
  "react": "^18.0.0 || ^19.0.0",
46
61
  "react-dom": "^18.0.0 || ^19.0.0"
@@ -93,19 +108,5 @@
93
108
  "bugs": {
94
109
  "url": "https://github.com/55cancri/qstd/issues"
95
110
  },
96
- "homepage": "https://github.com/55cancri/qstd#readme",
97
- "scripts": {
98
- "build": "panda codegen && panda cssgen && tsup && node scripts/inject-css-import.js",
99
- "dev": "tsup --watch",
100
- "test": "vitest run",
101
- "test:watch": "vitest",
102
- "test:all": "pnpx tsx tests/test-all.ts",
103
- "test:block": "node tests/test-block.tsx",
104
- "test:playground": "node tests/playground-e2e.mjs",
105
- "typecheck": "tsc --noEmit",
106
- "typecheck:perf": "tsc --noEmit --extendedDiagnostics",
107
- "typecheck:trace": "tsc --noEmit --generateTrace ./performance/ts-trace",
108
- "analyze:tsserver": "bash performance/analyze-tsserver.sh",
109
- "lint": "eslint src --ext ts,tsx"
110
- }
111
- }
111
+ "homepage": "https://github.com/55cancri/qstd#readme"
112
+ }