@fpkit/acss 0.6.2 → 1.0.0-beta.1
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/libs/components/alert/alert.css +1 -1
- package/libs/components/alert/alert.css.map +1 -1
- package/libs/components/alert/alert.min.css +2 -2
- package/libs/components/badge/badge.css +1 -1
- package/libs/components/badge/badge.css.map +1 -1
- package/libs/components/badge/badge.min.css +2 -2
- package/libs/components/breadcrumbs/breadcrumb.css +1 -1
- package/libs/components/breadcrumbs/breadcrumb.css.map +1 -1
- package/libs/components/breadcrumbs/breadcrumb.min.css +2 -2
- package/libs/components/buttons/button.css +1 -1
- package/libs/components/buttons/button.css.map +1 -1
- package/libs/components/buttons/button.min.css +2 -2
- package/libs/components/cards/card.css +1 -1
- package/libs/components/cards/card.css.map +1 -1
- package/libs/components/cards/card.min.css +2 -2
- package/libs/components/details/details.css +1 -1
- package/libs/components/details/details.css.map +1 -1
- package/libs/components/details/details.min.css +2 -2
- package/libs/components/dialog/dialog.css +1 -1
- package/libs/components/dialog/dialog.css.map +1 -1
- package/libs/components/dialog/dialog.min.css +2 -2
- package/libs/components/form/form.css +1 -1
- package/libs/components/form/form.css.map +1 -1
- package/libs/components/form/form.min.css +2 -2
- package/libs/components/icons/icon.d.cts +32 -32
- package/libs/components/icons/icon.d.ts +32 -32
- package/libs/components/images/img.css +1 -1
- package/libs/components/images/img.css.map +1 -1
- package/libs/components/images/img.min.css +2 -2
- package/libs/components/layout/landmarks.css +1 -1
- package/libs/components/layout/landmarks.css.map +1 -1
- package/libs/components/layout/landmarks.min.css +2 -2
- package/libs/components/link/link.css +1 -1
- package/libs/components/link/link.css.map +1 -1
- package/libs/components/link/link.min.css +2 -2
- package/libs/components/nav/nav.css +1 -1
- package/libs/components/nav/nav.css.map +1 -1
- package/libs/components/nav/nav.min.css +2 -2
- package/libs/components/progress/progress.css +1 -1
- package/libs/components/progress/progress.css.map +1 -1
- package/libs/components/progress/progress.min.css +2 -2
- package/libs/components/tag/tag.css +1 -1
- package/libs/components/tag/tag.css.map +1 -1
- package/libs/components/tag/tag.min.css +2 -2
- package/libs/index.css +1 -1
- package/libs/index.css.map +1 -1
- package/package.json +1 -1
- package/src/components/alert/alert.scss +4 -4
- package/src/components/alert/alert.scss.backup +184 -0
- package/src/components/alert/alert.stories.tsx +53 -2
- package/src/components/badge/badge.scss +2 -2
- package/src/components/badge/badge.scss.backup +39 -0
- package/src/components/badge/badge.stories.tsx +40 -0
- package/src/components/breadcrumbs/breadcrumb.scss +5 -5
- package/src/components/breadcrumbs/breadcrumb.scss.backup +35 -0
- package/src/components/breadcrumbs/breadcrumb.stories.tsx +17 -1
- package/src/components/buttons/button.scss +27 -27
- package/src/components/buttons/button.scss.backup +145 -0
- package/src/components/buttons/button.stories.tsx +188 -2
- package/src/components/cards/card.scss +39 -5
- package/src/components/cards/card.scss.backup +67 -0
- package/src/components/cards/card.stories.tsx +183 -0
- package/src/components/details/details.scss +14 -14
- package/src/components/details/details.scss.backup +126 -0
- package/src/components/details/details.stories.tsx +40 -0
- package/src/components/dialog/dialog.scss +3 -3
- package/src/components/dialog/dialog.scss.backup +126 -0
- package/src/components/form/form.scss +25 -9
- package/src/components/form/form.scss.backup +87 -0
- package/src/components/form/form.stories.tsx +271 -0
- package/src/components/form/input.stories.tsx +158 -0
- package/src/components/images/figure.stories.tsx +41 -1
- package/src/components/images/img.scss +8 -8
- package/src/components/images/img.scss.backup +59 -0
- package/src/components/layout/_header.scss +14 -14
- package/src/components/layout/_header.scss.backup +72 -0
- package/src/components/layout/landmarks.scss +7 -7
- package/src/components/layout/landmarks.scss.backup +51 -0
- package/src/components/layout/landmarks.stories.tsx +42 -0
- package/src/components/link/link.scss +5 -5
- package/src/components/link/link.scss.backup +145 -0
- package/src/components/link/link.stories.tsx +38 -2
- package/src/components/nav/nav.scss +17 -17
- package/src/components/nav/nav.scss.backup +123 -0
- package/src/components/nav/nav.stories.tsx +35 -1
- package/src/components/progress/progress.scss +7 -7
- package/src/components/progress/progress.scss.backup +70 -0
- package/src/components/tag/tag.scss +10 -10
- package/src/components/tag/tag.scss.backup +130 -0
- package/src/components/tag/tag.stories.tsx +23 -2
- package/src/styles/alert/alert.css +4 -4
- package/src/styles/badge/badge.css +2 -2
- package/src/styles/breadcrumbs/breadcrumb.css +5 -5
- package/src/styles/buttons/button.css +26 -27
- package/src/styles/buttons/button.css.map +1 -1
- package/src/styles/cards/card.css +35 -5
- package/src/styles/cards/card.css.map +1 -1
- package/src/styles/details/details.css +14 -14
- package/src/styles/dialog/dialog.css +3 -3
- package/src/styles/form/form.css +20 -10
- package/src/styles/form/form.css.map +1 -1
- package/src/styles/images/img.css +8 -8
- package/src/styles/index.css +170 -131
- package/src/styles/index.css.map +1 -1
- package/src/styles/layout/landmarks.css +21 -21
- package/src/styles/link/link.css +5 -5
- package/src/styles/nav/nav.css +17 -17
- package/src/styles/progress/progress.css +6 -6
- package/src/styles/tag/tag.css +4 -4
|
@@ -628,3 +628,274 @@ export const WithOnEnterHandler: Story = {
|
|
|
628
628
|
});
|
|
629
629
|
},
|
|
630
630
|
};
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* CSS Variable Customization
|
|
634
|
+
*
|
|
635
|
+
* Demonstrates how to customize form/input appearance using the new standardized
|
|
636
|
+
* CSS custom property naming convention.
|
|
637
|
+
*
|
|
638
|
+
* New variable naming patterns:
|
|
639
|
+
* - Logical properties: `--input-padding-inline`, `--input-padding-block`
|
|
640
|
+
* - Full property names: `--input-width`, `--input-radius`, `--input-border`
|
|
641
|
+
* - Approved abbreviations: `--input-fs` (font-size), `--input-bg` (background)
|
|
642
|
+
* - State variables: `--input-focus-outline`, `--input-disabled-bg`
|
|
643
|
+
*/
|
|
644
|
+
export const Customization: Story = {
|
|
645
|
+
render: () => (
|
|
646
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
|
|
647
|
+
{/* Custom input styling */}
|
|
648
|
+
<div>
|
|
649
|
+
<h4>Custom Input Styling</h4>
|
|
650
|
+
<FormComponent aria-label="Custom input example">
|
|
651
|
+
<FormComponent.Field label="Name" labelFor="custom-name">
|
|
652
|
+
<FormComponent.Input
|
|
653
|
+
id="custom-name"
|
|
654
|
+
name="name"
|
|
655
|
+
placeholder="Enter your name"
|
|
656
|
+
styles={{
|
|
657
|
+
"--input-padding-inline": "1.5rem",
|
|
658
|
+
"--input-padding-block": "0.75rem",
|
|
659
|
+
"--input-fs": "1.125rem",
|
|
660
|
+
"--input-radius": "0.5rem",
|
|
661
|
+
"--input-border": "2px solid #0066cc",
|
|
662
|
+
}}
|
|
663
|
+
/>
|
|
664
|
+
</FormComponent.Field>
|
|
665
|
+
</FormComponent>
|
|
666
|
+
</div>
|
|
667
|
+
|
|
668
|
+
{/* Compact form */}
|
|
669
|
+
<div>
|
|
670
|
+
<h4>Compact Form</h4>
|
|
671
|
+
<FormComponent aria-label="Compact form example">
|
|
672
|
+
<FormComponent.Field label="Email" labelFor="compact-email">
|
|
673
|
+
<FormComponent.Input
|
|
674
|
+
id="compact-email"
|
|
675
|
+
name="email"
|
|
676
|
+
type="email"
|
|
677
|
+
styles={{
|
|
678
|
+
"--input-padding-inline": "0.75rem",
|
|
679
|
+
"--input-padding-block": "0.5rem",
|
|
680
|
+
"--input-fs": "0.875rem",
|
|
681
|
+
"--input-radius": "0.25rem",
|
|
682
|
+
}}
|
|
683
|
+
/>
|
|
684
|
+
</FormComponent.Field>
|
|
685
|
+
</FormComponent>
|
|
686
|
+
</div>
|
|
687
|
+
|
|
688
|
+
{/* Custom focus states */}
|
|
689
|
+
<div>
|
|
690
|
+
<h4>Custom Focus States</h4>
|
|
691
|
+
<FormComponent aria-label="Focus state example">
|
|
692
|
+
<FormComponent.Field label="Username" labelFor="focus-username">
|
|
693
|
+
<FormComponent.Input
|
|
694
|
+
id="focus-username"
|
|
695
|
+
name="username"
|
|
696
|
+
placeholder="Try focusing this input"
|
|
697
|
+
styles={{
|
|
698
|
+
"--input-focus-outline": "3px solid #0066cc",
|
|
699
|
+
"--input-focus-outline-offset": "2px",
|
|
700
|
+
"--input-border": "2px solid #ddd",
|
|
701
|
+
}}
|
|
702
|
+
/>
|
|
703
|
+
</FormComponent.Field>
|
|
704
|
+
</FormComponent>
|
|
705
|
+
</div>
|
|
706
|
+
|
|
707
|
+
{/* Custom textarea */}
|
|
708
|
+
<div>
|
|
709
|
+
<h4>Custom Textarea</h4>
|
|
710
|
+
<FormComponent aria-label="Textarea example">
|
|
711
|
+
<FormComponent.Field label="Message" labelFor="custom-message">
|
|
712
|
+
<FormComponent.Textarea
|
|
713
|
+
id="custom-message"
|
|
714
|
+
name="message"
|
|
715
|
+
placeholder="Enter your message"
|
|
716
|
+
rows={4}
|
|
717
|
+
styles={{
|
|
718
|
+
"--input-padding-inline": "1rem",
|
|
719
|
+
"--input-padding-block": "1rem",
|
|
720
|
+
"--input-fs": "1rem",
|
|
721
|
+
"--input-radius": "0.75rem",
|
|
722
|
+
"--input-border": "1px solid #ccc",
|
|
723
|
+
"--input-width": "100%",
|
|
724
|
+
}}
|
|
725
|
+
/>
|
|
726
|
+
</FormComponent.Field>
|
|
727
|
+
</FormComponent>
|
|
728
|
+
</div>
|
|
729
|
+
|
|
730
|
+
{/* Custom select */}
|
|
731
|
+
<div>
|
|
732
|
+
<h4>Custom Select</h4>
|
|
733
|
+
<FormComponent aria-label="Select example">
|
|
734
|
+
<FormComponent.Field label="Country" labelFor="custom-country">
|
|
735
|
+
<FormComponent.Select
|
|
736
|
+
id="custom-country"
|
|
737
|
+
name="country"
|
|
738
|
+
styles={{
|
|
739
|
+
"--input-padding-inline": "1.25rem",
|
|
740
|
+
"--input-padding-block": "0.625rem",
|
|
741
|
+
"--input-fs": "1rem",
|
|
742
|
+
"--input-radius": "0.5rem",
|
|
743
|
+
"--input-border": "2px solid #28a745",
|
|
744
|
+
"--input-bg": "#f0f9f4",
|
|
745
|
+
}}
|
|
746
|
+
>
|
|
747
|
+
<FormComponent.Select.Option value="">Select country</FormComponent.Select.Option>
|
|
748
|
+
<FormComponent.Select.Option value="us">United States</FormComponent.Select.Option>
|
|
749
|
+
<FormComponent.Select.Option value="ca">Canada</FormComponent.Select.Option>
|
|
750
|
+
<FormComponent.Select.Option value="uk">United Kingdom</FormComponent.Select.Option>
|
|
751
|
+
</FormComponent.Select>
|
|
752
|
+
</FormComponent.Field>
|
|
753
|
+
</FormComponent>
|
|
754
|
+
</div>
|
|
755
|
+
|
|
756
|
+
{/* Dark theme example */}
|
|
757
|
+
<div
|
|
758
|
+
style={{
|
|
759
|
+
background: "#1a1a1a",
|
|
760
|
+
padding: "1.5rem",
|
|
761
|
+
borderRadius: "0.5rem",
|
|
762
|
+
}}
|
|
763
|
+
>
|
|
764
|
+
<h4 style={{ color: "white", marginTop: 0 }}>Dark Theme Example</h4>
|
|
765
|
+
<FormComponent aria-label="Dark theme form">
|
|
766
|
+
<FormComponent.Field label="Email" labelFor="dark-email">
|
|
767
|
+
<FormComponent.Input
|
|
768
|
+
id="dark-email"
|
|
769
|
+
name="email"
|
|
770
|
+
type="email"
|
|
771
|
+
placeholder="email@example.com"
|
|
772
|
+
styles={{
|
|
773
|
+
"--input-bg": "#2a2a2a",
|
|
774
|
+
"--input-color": "#e5e7eb",
|
|
775
|
+
"--input-border": "1px solid #4b5563",
|
|
776
|
+
"--input-padding-inline": "1rem",
|
|
777
|
+
"--input-padding-block": "0.75rem",
|
|
778
|
+
"--input-radius": "0.5rem",
|
|
779
|
+
"--input-focus-outline": "2px solid #3b82f6",
|
|
780
|
+
"--placeholder-color": "#9ca3af",
|
|
781
|
+
}}
|
|
782
|
+
/>
|
|
783
|
+
</FormComponent.Field>
|
|
784
|
+
<FormComponent.Field label="Comments" labelFor="dark-comments" style={{ marginTop: "1rem" }}>
|
|
785
|
+
<FormComponent.Textarea
|
|
786
|
+
id="dark-comments"
|
|
787
|
+
name="comments"
|
|
788
|
+
placeholder="Your feedback..."
|
|
789
|
+
rows={3}
|
|
790
|
+
styles={{
|
|
791
|
+
"--input-bg": "#2a2a2a",
|
|
792
|
+
"--input-color": "#e5e7eb",
|
|
793
|
+
"--input-border": "1px solid #4b5563",
|
|
794
|
+
"--input-padding-inline": "1rem",
|
|
795
|
+
"--input-padding-block": "0.75rem",
|
|
796
|
+
"--input-radius": "0.5rem",
|
|
797
|
+
"--input-focus-outline": "2px solid #3b82f6",
|
|
798
|
+
"--placeholder-color": "#9ca3af",
|
|
799
|
+
}}
|
|
800
|
+
/>
|
|
801
|
+
</FormComponent.Field>
|
|
802
|
+
</FormComponent>
|
|
803
|
+
</div>
|
|
804
|
+
|
|
805
|
+
{/* Disabled state customization */}
|
|
806
|
+
<div>
|
|
807
|
+
<h4>Custom Disabled State</h4>
|
|
808
|
+
<FormComponent aria-label="Disabled state example">
|
|
809
|
+
<FormComponent.Field label="Disabled Input" labelFor="disabled-custom">
|
|
810
|
+
<FormComponent.Input
|
|
811
|
+
id="disabled-custom"
|
|
812
|
+
name="disabled"
|
|
813
|
+
disabled
|
|
814
|
+
value="This input is disabled"
|
|
815
|
+
styles={{
|
|
816
|
+
"--input-disabled-bg": "#f5f5f5",
|
|
817
|
+
"--input-disabled-opacity": "0.6",
|
|
818
|
+
"--input-padding-inline": "1rem",
|
|
819
|
+
"--input-padding-block": "0.75rem",
|
|
820
|
+
}}
|
|
821
|
+
/>
|
|
822
|
+
</FormComponent.Field>
|
|
823
|
+
</FormComponent>
|
|
824
|
+
</div>
|
|
825
|
+
</div>
|
|
826
|
+
),
|
|
827
|
+
parameters: {
|
|
828
|
+
docs: {
|
|
829
|
+
description: {
|
|
830
|
+
story: `
|
|
831
|
+
## Available CSS Variables
|
|
832
|
+
|
|
833
|
+
### Base Properties
|
|
834
|
+
- \`--input-padding-inline\`: Horizontal padding (logical property)
|
|
835
|
+
- \`--input-padding-block\`: Vertical padding (logical property)
|
|
836
|
+
- \`--input-width\`: Input width
|
|
837
|
+
- \`--input-radius\`: Border radius
|
|
838
|
+
- \`--input-color\`: Text color
|
|
839
|
+
- \`--input-bg\`: Background color
|
|
840
|
+
- \`--input-border\`: Border style
|
|
841
|
+
|
|
842
|
+
### Typography (Approved Abbreviations)
|
|
843
|
+
- \`--input-fs\`: Font size
|
|
844
|
+
|
|
845
|
+
### Focus State Variables
|
|
846
|
+
- \`--input-focus-outline\`: Outline on focus
|
|
847
|
+
- \`--input-focus-outline-offset\`: Outline offset on focus
|
|
848
|
+
|
|
849
|
+
### Disabled State Variables
|
|
850
|
+
- \`--input-disabled-bg\`: Background color when disabled
|
|
851
|
+
- \`--input-disabled-opacity\`: Opacity when disabled
|
|
852
|
+
|
|
853
|
+
### Placeholder Variables
|
|
854
|
+
- \`--placeholder-fs\`: Placeholder font size
|
|
855
|
+
- \`--placeholder-color\`: Placeholder text color
|
|
856
|
+
|
|
857
|
+
### Migration from Old Names
|
|
858
|
+
- ❌ \`--input-px\` → ✅ \`--input-padding-inline\`
|
|
859
|
+
- ❌ \`--input-py\` → ✅ \`--input-padding-block\`
|
|
860
|
+
- ❌ \`--input-w\` → ✅ \`--input-width\`
|
|
861
|
+
|
|
862
|
+
## Usage Examples
|
|
863
|
+
|
|
864
|
+
### Custom Input
|
|
865
|
+
\`\`\`tsx
|
|
866
|
+
<Form.Input
|
|
867
|
+
styles={{
|
|
868
|
+
"--input-padding-inline": "1.5rem",
|
|
869
|
+
"--input-padding-block": "0.75rem",
|
|
870
|
+
"--input-fs": "1.125rem",
|
|
871
|
+
"--input-radius": "0.5rem",
|
|
872
|
+
}}
|
|
873
|
+
/>
|
|
874
|
+
\`\`\`
|
|
875
|
+
|
|
876
|
+
### Custom Focus State
|
|
877
|
+
\`\`\`tsx
|
|
878
|
+
<Form.Input
|
|
879
|
+
styles={{
|
|
880
|
+
"--input-focus-outline": "3px solid #0066cc",
|
|
881
|
+
"--input-focus-outline-offset": "2px",
|
|
882
|
+
}}
|
|
883
|
+
/>
|
|
884
|
+
\`\`\`
|
|
885
|
+
|
|
886
|
+
### Dark Theme Input
|
|
887
|
+
\`\`\`tsx
|
|
888
|
+
<Form.Input
|
|
889
|
+
styles={{
|
|
890
|
+
"--input-bg": "#2a2a2a",
|
|
891
|
+
"--input-color": "#e5e7eb",
|
|
892
|
+
"--input-border": "1px solid #4b5563",
|
|
893
|
+
"--input-focus-outline": "2px solid #3b82f6",
|
|
894
|
+
}}
|
|
895
|
+
/>
|
|
896
|
+
\`\`\`
|
|
897
|
+
`,
|
|
898
|
+
},
|
|
899
|
+
},
|
|
900
|
+
},
|
|
901
|
+
} as Story;
|
|
@@ -221,3 +221,161 @@ export const UrlInput: Story = {
|
|
|
221
221
|
expect(input).toHaveValue("https://example.com");
|
|
222
222
|
},
|
|
223
223
|
} as Story;
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* CSS Variable Customization
|
|
227
|
+
*
|
|
228
|
+
* Demonstrates how to customize input appearance using the new standardized
|
|
229
|
+
* CSS custom property naming convention.
|
|
230
|
+
*
|
|
231
|
+
* New variable naming patterns:
|
|
232
|
+
* - Logical properties: `--input-padding-inline`, `--input-padding-block`
|
|
233
|
+
* - Full property names: `--input-width`, `--input-radius`, `--input-border`
|
|
234
|
+
* - Focus state variables: `--input-focus-outline`, `--input-focus-outline-offset`
|
|
235
|
+
* - Disabled state variables: `--input-disabled-bg`, `--input-disabled-opacity`
|
|
236
|
+
* - Approved abbreviations: `--input-fs` (font-size)
|
|
237
|
+
*/
|
|
238
|
+
export const Customization: Story = {
|
|
239
|
+
render: () => (
|
|
240
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "2rem", maxWidth: "600px" }}>
|
|
241
|
+
{/* Custom brand styling */}
|
|
242
|
+
<div>
|
|
243
|
+
<h4>Custom Brand Styling</h4>
|
|
244
|
+
<Input
|
|
245
|
+
type="text"
|
|
246
|
+
placeholder="Enter your email"
|
|
247
|
+
styles={{
|
|
248
|
+
"--input-padding-inline": "1rem",
|
|
249
|
+
"--input-padding-block": "0.75rem",
|
|
250
|
+
"--input-border": "2px solid #0066cc",
|
|
251
|
+
"--input-radius": "0.5rem",
|
|
252
|
+
"--input-fs": "1rem",
|
|
253
|
+
}}
|
|
254
|
+
/>
|
|
255
|
+
</div>
|
|
256
|
+
|
|
257
|
+
{/* Custom focus indicator (WCAG compliant) */}
|
|
258
|
+
<div>
|
|
259
|
+
<h4>Custom Focus Indicator (WCAG AA Compliant)</h4>
|
|
260
|
+
<Input
|
|
261
|
+
type="text"
|
|
262
|
+
placeholder="Focus me to see custom outline"
|
|
263
|
+
styles={{
|
|
264
|
+
"--input-focus-outline": "3px solid #0066cc",
|
|
265
|
+
"--input-focus-outline-offset": "2px",
|
|
266
|
+
"--input-border": "1px solid #ccc",
|
|
267
|
+
}}
|
|
268
|
+
/>
|
|
269
|
+
</div>
|
|
270
|
+
|
|
271
|
+
{/* Custom disabled state */}
|
|
272
|
+
<div>
|
|
273
|
+
<h4>Custom Disabled State</h4>
|
|
274
|
+
<Input
|
|
275
|
+
type="text"
|
|
276
|
+
disabled={true}
|
|
277
|
+
placeholder="Disabled input"
|
|
278
|
+
value="Cannot edit"
|
|
279
|
+
styles={{
|
|
280
|
+
"--input-disabled-bg": "#ffe6e6",
|
|
281
|
+
"--input-disabled-opacity": "0.7",
|
|
282
|
+
"--input-border": "1px dashed #999",
|
|
283
|
+
}}
|
|
284
|
+
/>
|
|
285
|
+
</div>
|
|
286
|
+
|
|
287
|
+
{/* Compact input */}
|
|
288
|
+
<div>
|
|
289
|
+
<h4>Compact Input (Logical Properties)</h4>
|
|
290
|
+
<Input
|
|
291
|
+
type="text"
|
|
292
|
+
placeholder="Compact"
|
|
293
|
+
styles={{
|
|
294
|
+
"--input-padding-inline": "0.5rem",
|
|
295
|
+
"--input-padding-block": "0.25rem",
|
|
296
|
+
"--input-fs": "0.875rem",
|
|
297
|
+
"--input-width": "200px",
|
|
298
|
+
}}
|
|
299
|
+
/>
|
|
300
|
+
</div>
|
|
301
|
+
|
|
302
|
+
{/* Spacious input */}
|
|
303
|
+
<div>
|
|
304
|
+
<h4>Spacious Input</h4>
|
|
305
|
+
<Input
|
|
306
|
+
type="text"
|
|
307
|
+
placeholder="Spacious"
|
|
308
|
+
styles={{
|
|
309
|
+
"--input-padding-inline": "1.5rem",
|
|
310
|
+
"--input-padding-block": "1rem",
|
|
311
|
+
"--input-fs": "1.125rem",
|
|
312
|
+
"--input-radius": "0.75rem",
|
|
313
|
+
}}
|
|
314
|
+
/>
|
|
315
|
+
</div>
|
|
316
|
+
|
|
317
|
+
{/* Dark theme example */}
|
|
318
|
+
<div
|
|
319
|
+
style={{
|
|
320
|
+
background: "#1a1a1a",
|
|
321
|
+
padding: "1.5rem",
|
|
322
|
+
borderRadius: "0.5rem",
|
|
323
|
+
}}
|
|
324
|
+
>
|
|
325
|
+
<h4 style={{ color: "white", marginTop: 0 }}>Dark Theme Example</h4>
|
|
326
|
+
<Input
|
|
327
|
+
type="text"
|
|
328
|
+
placeholder="Search..."
|
|
329
|
+
styles={{
|
|
330
|
+
"--input-bg": "#2a2a2a",
|
|
331
|
+
"--input-color": "white",
|
|
332
|
+
"--input-border": "1px solid #4b5563",
|
|
333
|
+
"--input-focus-outline": "2px solid #3b82f6",
|
|
334
|
+
"--input-focus-outline-offset": "0",
|
|
335
|
+
"--placeholder-color": "#9ca3af",
|
|
336
|
+
}}
|
|
337
|
+
/>
|
|
338
|
+
</div>
|
|
339
|
+
</div>
|
|
340
|
+
),
|
|
341
|
+
parameters: {
|
|
342
|
+
docs: {
|
|
343
|
+
description: {
|
|
344
|
+
story: `
|
|
345
|
+
## Available CSS Variables
|
|
346
|
+
|
|
347
|
+
### Base Properties
|
|
348
|
+
- \`--input-padding-inline\`: Horizontal padding (logical property)
|
|
349
|
+
- \`--input-padding-block\`: Vertical padding (logical property)
|
|
350
|
+
- \`--input-width\`: Input width (default: clamp(200px, 100%, 500px))
|
|
351
|
+
- \`--input-border\`: Border style
|
|
352
|
+
- \`--input-radius\`: Border radius
|
|
353
|
+
- \`--input-bg\`: Background color
|
|
354
|
+
- \`--input-outline\`: Default outline
|
|
355
|
+
|
|
356
|
+
### Typography (Approved Abbreviation)
|
|
357
|
+
- \`--input-fs\`: Font size
|
|
358
|
+
|
|
359
|
+
### Focus State Variables (NEW)
|
|
360
|
+
- \`--input-focus-outline\`: Outline when focused
|
|
361
|
+
- \`--input-focus-outline-offset\`: Outline offset (for WCAG compliance)
|
|
362
|
+
|
|
363
|
+
### Disabled State Variables (NEW)
|
|
364
|
+
- \`--input-disabled-bg\`: Background when disabled
|
|
365
|
+
- \`--input-disabled-opacity\`: Opacity when disabled
|
|
366
|
+
- \`--input-disabled-cursor\`: Cursor style when disabled
|
|
367
|
+
|
|
368
|
+
### Placeholder Variables
|
|
369
|
+
- \`--placeholder-color\`: Placeholder text color
|
|
370
|
+
- \`--placeholder-fs\`: Placeholder font size
|
|
371
|
+
- \`--placeholder-style\`: Placeholder font style (italic)
|
|
372
|
+
|
|
373
|
+
### Migration from Old Names
|
|
374
|
+
- ❌ \`--input-px\` → ✅ \`--input-padding-inline\`
|
|
375
|
+
- ❌ \`--input-py\` → ✅ \`--input-padding-block\`
|
|
376
|
+
- ❌ \`--input-w\` → ✅ \`--input-width\`
|
|
377
|
+
`,
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
},
|
|
381
|
+
} as Story;
|
|
@@ -11,7 +11,47 @@ const meta: Meta<typeof Figure> = {
|
|
|
11
11
|
actions: { argTypesRegex: "^on.*" },
|
|
12
12
|
docs: {
|
|
13
13
|
description: {
|
|
14
|
-
component:
|
|
14
|
+
component: `A semantic figure component for displaying images with captions, using CSS custom properties for flexible styling.
|
|
15
|
+
|
|
16
|
+
## CSS Variables
|
|
17
|
+
|
|
18
|
+
Customize the Figure and Image appearance using CSS custom properties:
|
|
19
|
+
|
|
20
|
+
### Image Variables (img[alt])
|
|
21
|
+
- \`--img-max-width\`: Maximum width (default: \`100%\`)
|
|
22
|
+
- \`--img-height\`: Height value (default: \`auto\`)
|
|
23
|
+
- \`--img-display\`: Display type (default: \`inline-block\`)
|
|
24
|
+
- \`--img-object-fit\`: Object fit mode (default: \`cover\`)
|
|
25
|
+
- \`--img-object-position\`: Object position (default: \`center\`)
|
|
26
|
+
- \`--img-aspect-ratio\`: Aspect ratio (default: \`auto 2/3\`)
|
|
27
|
+
|
|
28
|
+
### Figure Variables (figure:has(img[alt]))
|
|
29
|
+
- \`--fig-display\`: Display type (default: \`flex\`)
|
|
30
|
+
- \`--fig-padding\`: Figure padding (default: \`0.5rem\`)
|
|
31
|
+
- \`--fig-bg\`: Background color (default: \`rgba(245, 245, 245, 0.683)\`)
|
|
32
|
+
- \`--fig-width\`: Max width constraint (default: \`fit-content\`)
|
|
33
|
+
- \`--fig-bottom\`: Figcaption bottom offset (default: \`var(--fig-padding)\`)
|
|
34
|
+
- \`--fig-left\`: Figcaption left offset (default: \`var(--fig-padding)\`)
|
|
35
|
+
- \`--fig-right\`: Figcaption right offset (default: \`var(--fig-padding)\`)
|
|
36
|
+
|
|
37
|
+
### Figcaption Variables
|
|
38
|
+
- \`--caption-padding\`: Caption padding (default: \`var(--spc-3)\`)
|
|
39
|
+
|
|
40
|
+
**Example:**
|
|
41
|
+
\`\`\`css
|
|
42
|
+
figure:has(img[alt]) {
|
|
43
|
+
--fig-padding: 1rem;
|
|
44
|
+
--fig-bg: #f5f5f5;
|
|
45
|
+
--fig-width: 40rem;
|
|
46
|
+
--caption-padding: 1.5rem;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
img[alt] {
|
|
50
|
+
--img-max-width: 100%;
|
|
51
|
+
--img-object-fit: contain;
|
|
52
|
+
--img-aspect-ratio: 16/9;
|
|
53
|
+
}
|
|
54
|
+
\`\`\``,
|
|
15
55
|
},
|
|
16
56
|
},
|
|
17
57
|
},
|
|
@@ -39,20 +39,20 @@ img[alt] {
|
|
|
39
39
|
figure {
|
|
40
40
|
&:has(img[alt]) {
|
|
41
41
|
--fig-display: flex;
|
|
42
|
-
--fig-
|
|
42
|
+
--fig-padding: 0.5rem;
|
|
43
43
|
--fig-bg: rgba(245, 245, 245, 0.683);
|
|
44
|
-
--fig-
|
|
44
|
+
--fig-width: fit-content;
|
|
45
45
|
display: var(--fig-display);
|
|
46
46
|
position: relative;
|
|
47
|
-
padding: var(--fig-
|
|
47
|
+
padding: var(--fig-padding);
|
|
48
48
|
background-color: var(--fig-bg);
|
|
49
|
-
max-width: var(--fig-
|
|
49
|
+
max-width: var(--fig-width);
|
|
50
50
|
> figcaption {
|
|
51
51
|
position: absolute;
|
|
52
|
-
bottom: var(--fig-bottom, var(--fig-
|
|
53
|
-
left: var(--fig-left, var(--fig-
|
|
54
|
-
right: var(--fig-right, var(--fig-
|
|
55
|
-
padding: var(--caption-
|
|
52
|
+
bottom: var(--fig-bottom, var(--fig-padding));
|
|
53
|
+
left: var(--fig-left, var(--fig-padding));
|
|
54
|
+
right: var(--fig-right, var(--fig-padding));
|
|
55
|
+
padding: var(--caption-padding, var(--spc-3));
|
|
56
56
|
background-color: var(--fig-bg);
|
|
57
57
|
}
|
|
58
58
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image component styles
|
|
3
|
+
*
|
|
4
|
+
* Applies to all images with alt attribute (both decorative alt="" and semantic).
|
|
5
|
+
* Uses CSS custom properties for flexible theming and responsive behavior.
|
|
6
|
+
*/
|
|
7
|
+
img[alt] {
|
|
8
|
+
/* CSS Custom Properties - Override these for customization */
|
|
9
|
+
--img-max-width: 100%;
|
|
10
|
+
--img-height: auto;
|
|
11
|
+
--img-object-fit: cover;
|
|
12
|
+
--img-object-position: center;
|
|
13
|
+
--img-aspect-ratio: auto 2/3;
|
|
14
|
+
--img-display: inline-block;
|
|
15
|
+
|
|
16
|
+
/* Layout - Responsive by default */
|
|
17
|
+
max-width: var(--img-max-width);
|
|
18
|
+
max-inline-size: var(--img-max-width); /* Logical property for i18n */
|
|
19
|
+
block-size: var(--img-height);
|
|
20
|
+
display: var(--img-display);
|
|
21
|
+
vertical-align: middle;
|
|
22
|
+
|
|
23
|
+
/* Object fitting for responsive images */
|
|
24
|
+
object-fit: var(--img-object-fit);
|
|
25
|
+
object-position: var(--img-object-position);
|
|
26
|
+
aspect-ratio: var(--img-aspect-ratio);
|
|
27
|
+
|
|
28
|
+
/* Accessibility - Italic font for broken image alt text */
|
|
29
|
+
font-style: italic;
|
|
30
|
+
|
|
31
|
+
/* Background for loading state */
|
|
32
|
+
background-size: cover;
|
|
33
|
+
background-repeat: no-repeat;
|
|
34
|
+
|
|
35
|
+
/* Shape margin for text wrapping */
|
|
36
|
+
shape-margin: var(--spc-3);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
figure {
|
|
40
|
+
&:has(img[alt]) {
|
|
41
|
+
--fig-display: flex;
|
|
42
|
+
--fig-p: 0.5rem;
|
|
43
|
+
--fig-bg: rgba(245, 245, 245, 0.683);
|
|
44
|
+
--fig-w: fit-content;
|
|
45
|
+
display: var(--fig-display);
|
|
46
|
+
position: relative;
|
|
47
|
+
padding: var(--fig-p);
|
|
48
|
+
background-color: var(--fig-bg);
|
|
49
|
+
max-width: var(--fig-w);
|
|
50
|
+
> figcaption {
|
|
51
|
+
position: absolute;
|
|
52
|
+
bottom: var(--fig-bottom, var(--fig-p));
|
|
53
|
+
left: var(--fig-left, var(--fig-p));
|
|
54
|
+
right: var(--fig-right, var(--fig-p));
|
|
55
|
+
padding: var(--caption-p, var(--spc-3));
|
|
56
|
+
background-color: var(--fig-bg);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -9,24 +9,24 @@ header,
|
|
|
9
9
|
--overlay-display: grid;
|
|
10
10
|
// Overlay padding
|
|
11
11
|
--overlay-padding: 2rem;
|
|
12
|
-
--overlay-
|
|
13
|
-
--overlay-
|
|
14
|
-
--overlay-max-
|
|
12
|
+
--overlay-width: 100%;
|
|
13
|
+
--overlay-height: 40vh;
|
|
14
|
+
--overlay-max-height: 500px;
|
|
15
15
|
--overlay-color: currentColor;
|
|
16
|
-
--overlay-content-
|
|
16
|
+
--overlay-content-width: 80%;
|
|
17
17
|
--overlay-gap: 2rem;
|
|
18
18
|
--overlay-bg: whitesmoke;
|
|
19
|
-
--overlay-
|
|
20
|
-
--overlay-
|
|
21
|
-
--overlay-
|
|
22
|
-
--overlay-
|
|
19
|
+
--overlay-padding-inline: auto;
|
|
20
|
+
--overlay-padding-block: auto;
|
|
21
|
+
--overlay-margin-inline: auto;
|
|
22
|
+
--overlay-margin-block: auto;
|
|
23
23
|
|
|
24
24
|
grid-template-areas: 'overlay';
|
|
25
25
|
display: var(--overlay-display);
|
|
26
26
|
place-items: var(--overlay-placement);
|
|
27
27
|
align-items: var(--overlay-placement);
|
|
28
|
-
min-height: var(--overlay-
|
|
29
|
-
width: var(--overlay-
|
|
28
|
+
min-height: var(--overlay-height);
|
|
29
|
+
width: var(--overlay-width);
|
|
30
30
|
color: var(--overlay-color);
|
|
31
31
|
background-color: var(--overlay-bg);
|
|
32
32
|
min-width: 20rem;
|
|
@@ -34,16 +34,16 @@ header,
|
|
|
34
34
|
grid-area: overlay;
|
|
35
35
|
}
|
|
36
36
|
> img {
|
|
37
|
-
width: var(--overlay-
|
|
37
|
+
width: var(--overlay-width);
|
|
38
38
|
// height: auto;
|
|
39
39
|
background-size: contain;
|
|
40
40
|
}
|
|
41
41
|
> div,
|
|
42
42
|
> section {
|
|
43
43
|
--overlay-display: flex;
|
|
44
|
-
max-width: var(--overlay-content-
|
|
44
|
+
max-width: var(--overlay-content-width);
|
|
45
45
|
padding-inline: var(--spc-4);
|
|
46
|
-
margin-inline: var(--overlay-
|
|
46
|
+
margin-inline: var(--overlay-margin-inline);
|
|
47
47
|
gap: var(--overlay-gap);
|
|
48
48
|
text-align: center;
|
|
49
49
|
p {
|
|
@@ -54,7 +54,7 @@ header,
|
|
|
54
54
|
}
|
|
55
55
|
> h1,
|
|
56
56
|
> h2 {
|
|
57
|
-
line-height: var(--header-
|
|
57
|
+
line-height: var(--header-line-height, 1.1);
|
|
58
58
|
font-weight: 500;
|
|
59
59
|
}
|
|
60
60
|
|