@wix/auto-patterns 1.21.0 → 1.22.0
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/dist/cjs/components/AutoPatternsCollectionComponent/AutoPatternsCollectionComponent.js +109 -0
- package/dist/cjs/components/AutoPatternsCollectionComponent/AutoPatternsCollectionComponent.js.map +1 -0
- package/dist/cjs/components/AutoPatternsCollectionPage/AutoPatternsCollectionPage.js +5 -14
- package/dist/cjs/components/AutoPatternsCollectionPage/AutoPatternsCollectionPage.js.map +1 -1
- package/dist/cjs/components/AutoPatternsCollectionPageContent/AutoPatternsCollectionPageContent.js +19 -68
- package/dist/cjs/components/AutoPatternsCollectionPageContent/AutoPatternsCollectionPageContent.js.map +1 -1
- package/dist/cjs/hooks/useActionCell.js +10 -2
- package/dist/cjs/hooks/useActionCell.js.map +1 -1
- package/dist/cjs/providers/PatternsWizardOverridesContext.js.map +1 -1
- package/dist/cjs/types/CollectionPageConfig.js.map +1 -1
- package/dist/cjs/types/actions/actionCell.js.map +1 -1
- package/dist/docs/action_cell.md +13 -3
- package/dist/docs/app_config_structure.md +7 -1
- package/dist/docs/auto-patterns-guide.md +201 -13
- package/dist/docs/custom_overrides.md +181 -9
- package/dist/esm/components/AutoPatternsCollectionComponent/AutoPatternsCollectionComponent.js +72 -0
- package/dist/esm/components/AutoPatternsCollectionComponent/AutoPatternsCollectionComponent.js.map +1 -0
- package/dist/esm/components/AutoPatternsCollectionPage/AutoPatternsCollectionPage.js +1 -3
- package/dist/esm/components/AutoPatternsCollectionPage/AutoPatternsCollectionPage.js.map +1 -1
- package/dist/esm/components/AutoPatternsCollectionPageContent/AutoPatternsCollectionPageContent.js +17 -48
- package/dist/esm/components/AutoPatternsCollectionPageContent/AutoPatternsCollectionPageContent.js.map +1 -1
- package/dist/esm/hooks/useActionCell.js +10 -2
- package/dist/esm/hooks/useActionCell.js.map +1 -1
- package/dist/esm/providers/PatternsWizardOverridesContext.js.map +1 -1
- package/dist/esm/types/CollectionPageConfig.js.map +1 -1
- package/dist/esm/types/actions/actionCell.js.map +1 -1
- package/dist/types/components/AutoPatternsCollectionComponent/AutoPatternsCollectionComponent.d.ts +7 -0
- package/dist/types/components/AutoPatternsCollectionComponent/AutoPatternsCollectionComponent.d.ts.map +1 -0
- package/dist/types/components/AutoPatternsCollectionPage/AutoPatternsCollectionPage.d.ts.map +1 -1
- package/dist/types/components/AutoPatternsCollectionPageContent/AutoPatternsCollectionPageContent.d.ts.map +1 -1
- package/dist/types/hooks/useActionCell.d.ts.map +1 -1
- package/dist/types/providers/PatternsWizardOverridesContext.d.ts +1 -1
- package/dist/types/providers/PatternsWizardOverridesContext.d.ts.map +1 -1
- package/dist/types/types/CollectionPageConfig.d.ts +7 -1
- package/dist/types/types/CollectionPageConfig.d.ts.map +1 -1
- package/dist/types/types/actions/actionCell.d.ts +1 -0
- package/dist/types/types/actions/actionCell.d.ts.map +1 -1
- package/package.json +7 -7
|
@@ -147,8 +147,9 @@ export interface AppConfig {
|
|
|
147
147
|
menu?: {}; // Same structure as primaryActions.menu
|
|
148
148
|
};
|
|
149
149
|
};
|
|
150
|
-
components: [
|
|
150
|
+
components: [ // Array of component configurations that can be collection components or custom slot components
|
|
151
151
|
{
|
|
152
|
+
type: 'collection'; // Component type for collection rendering (table/grid with full features)
|
|
152
153
|
entityPageId?: string; // ID of the entity page to navigate to when clicking a row
|
|
153
154
|
collection: {
|
|
154
155
|
collectionId: string; // ID of the Wix Data collection
|
|
@@ -249,6 +250,7 @@ export interface AppConfig {
|
|
|
249
250
|
};
|
|
250
251
|
};
|
|
251
252
|
};
|
|
253
|
+
alwaysVisible?: boolean; // Whether to always show the primary action (not just on hover)
|
|
252
254
|
};
|
|
253
255
|
secondaryActions?: {
|
|
254
256
|
items: {}[]; // Array of action configurations, same structure as primaryAction.item, can include dividers
|
|
@@ -366,6 +368,10 @@ export interface AppConfig {
|
|
|
366
368
|
};
|
|
367
369
|
}
|
|
368
370
|
]; // End of layout array
|
|
371
|
+
} |
|
|
372
|
+
{
|
|
373
|
+
type: 'custom'; // Component type for custom slot components
|
|
374
|
+
id: string; // Unique identifier that maps to a custom React component provided through PatternsWizardOverridesProvider slots
|
|
369
375
|
}
|
|
370
376
|
]; // End of components array
|
|
371
377
|
};
|
|
@@ -1356,6 +1362,10 @@ The ActionCell has a two-level structure:
|
|
|
1356
1362
|
|
|
1357
1363
|
Both properties are optional, but at least one should be provided for the ActionCell to be useful.
|
|
1358
1364
|
|
|
1365
|
+
### Primary Action Visibility Control
|
|
1366
|
+
|
|
1367
|
+
**New Feature**: Primary actions now support visibility control through the `alwaysVisible` property. By default, primary actions follow standard table interaction patterns (typically visible on hover), but you can configure them to be always visible for improved accessibility and user discovery.
|
|
1368
|
+
|
|
1359
1369
|
### Inline Secondary Actions
|
|
1360
1370
|
|
|
1361
1371
|
**New Feature**: By default, all secondary actions are hidden in a popover menu that appears when the user hovers over or clicks the "more actions" button. However, you can now configure some secondary actions to display inline directly in the table row for improved accessibility and reduced clicks.
|
|
@@ -1560,17 +1570,21 @@ Follow this decision process when implementing ActionCell:
|
|
|
1560
1570
|
- Most common operation (typically Edit) → Place in `primaryAction.item`
|
|
1561
1571
|
- Less common operations → Place in `secondaryActions.items` array
|
|
1562
1572
|
|
|
1563
|
-
3. **
|
|
1573
|
+
3. **Primary Action Visibility Strategy**:
|
|
1574
|
+
- **Standard Visibility** (`alwaysVisible: false` or omitted): Use for most cases where actions appear on interaction
|
|
1575
|
+
- **Always Visible** (`alwaysVisible: true`): Use for critical actions that need constant visibility or when user discovery is important
|
|
1576
|
+
|
|
1577
|
+
4. **Inline Secondary Actions Strategy**:
|
|
1564
1578
|
- **Action Prioritization**: Order `secondaryActions.items` by frequency of use (most used first)
|
|
1565
1579
|
- **Inline Count**: Use `inlineCount: 1-3` for optimal UX (avoid cluttering)
|
|
1566
1580
|
- **Visibility Control**:
|
|
1567
1581
|
- Use `inlineAlwaysVisible: false` (default) for cleaner visual appearance
|
|
1568
1582
|
- Use `inlineAlwaysVisible: true` only for critical actions requiring constant visibility
|
|
1569
1583
|
|
|
1570
|
-
|
|
1584
|
+
5. **Update Action Mode**:
|
|
1571
1585
|
- Complex, full-entity edits → Use `mode: "page"` to navigate to entity page
|
|
1572
1586
|
|
|
1573
|
-
|
|
1587
|
+
6. **Custom Implementation**:
|
|
1574
1588
|
- For `custom` actions, you must provide implementations in your code and register them with `PatternsWizardOverridesProvider`
|
|
1575
1589
|
|
|
1576
1590
|
### ActionCell Validation Checklist
|
|
@@ -1584,6 +1598,8 @@ AI agents should verify these requirements before generating ActionCell configur
|
|
|
1584
1598
|
✓ Delete action has a modal configuration
|
|
1585
1599
|
✓ Custom actions match implementations in overrides
|
|
1586
1600
|
✓ At least one of `primaryAction` or `secondaryActions` is provided
|
|
1601
|
+
✓ `alwaysVisible` property on primary actions (if specified) is a boolean value
|
|
1602
|
+
✓ Primary action visibility is properly considered for UX (use `alwaysVisible: true` for critical actions)
|
|
1587
1603
|
✓ `inlineCount` (if specified) is a non-negative number ≤ total secondary actions count
|
|
1588
1604
|
✓ `inlineAlwaysVisible` (if specified) is a boolean value
|
|
1589
1605
|
✓ Inline secondary actions configuration is applied only when secondary actions exist
|
|
@@ -2163,6 +2179,10 @@ your-page/
|
|
|
2163
2179
|
│ ├── index.tsx // Exports useColumns hook
|
|
2164
2180
|
│ ├── name.ts
|
|
2165
2181
|
│ └── date.ts
|
|
2182
|
+
├── slots/ // Custom slot components for collection pages
|
|
2183
|
+
│ ├── index.tsx // Exports useSlots hook
|
|
2184
|
+
│ ├── TopBannerComponent.tsx
|
|
2185
|
+
│ └── BottomStatsComponent.tsx
|
|
2166
2186
|
├── customComponents/ // Custom entity page components
|
|
2167
2187
|
│ ├── index.tsx // Exports useComponents hook
|
|
2168
2188
|
│ ├── CustomNameField.tsx
|
|
@@ -2170,16 +2190,12 @@ your-page/
|
|
|
2170
2190
|
├── modals/ // Custom modals
|
|
2171
2191
|
│ ├── index.tsx // Exports useModals hook
|
|
2172
2192
|
│ └── myCustomModal.tsx
|
|
2173
|
-
|
|
2193
|
+
├── customDataSources/ // Custom data sources
|
|
2174
2194
|
│ ├── index.tsx // Exports useCustomDataSources hook
|
|
2175
2195
|
│ └── myCustomDataSource.ts
|
|
2176
|
-
|
|
2177
|
-
│ ├── index.tsx
|
|
2178
|
-
│ └── groupByType.ts
|
|
2179
|
-
└── customComponents/ // Custom entity page components
|
|
2196
|
+
└── sections/ // Section renderers
|
|
2180
2197
|
├── index.tsx
|
|
2181
|
-
|
|
2182
|
-
└── InfoCard.tsx
|
|
2198
|
+
└── groupByType.ts
|
|
2183
2199
|
```
|
|
2184
2200
|
|
|
2185
2201
|
### Using Override Hooks in Your Page
|
|
@@ -2189,6 +2205,7 @@ In your page component, use the hook-based approach to access React context and
|
|
|
2189
2205
|
```tsx
|
|
2190
2206
|
import { useActions } from '../components/actions';
|
|
2191
2207
|
import { useColumns } from '../components/columns';
|
|
2208
|
+
import { useSlots } from '../components/slots';
|
|
2192
2209
|
import { useSections } from '../components/sections';
|
|
2193
2210
|
import { useComponents } from '../components/customComponents';
|
|
2194
2211
|
import { useModals } from '../components/modals';
|
|
@@ -2197,13 +2214,14 @@ import { useCustomDataSources } from '../components/customDataSources';
|
|
|
2197
2214
|
export default function YourPage() {
|
|
2198
2215
|
const actions = useActions();
|
|
2199
2216
|
const columns = useColumns();
|
|
2217
|
+
const slots = useSlots();
|
|
2200
2218
|
const sections = useSections();
|
|
2201
2219
|
const components = useComponents();
|
|
2202
2220
|
const modals = useModals();
|
|
2203
2221
|
const customDataSources = useCustomDataSources();
|
|
2204
2222
|
|
|
2205
2223
|
return (
|
|
2206
|
-
<PatternsWizardOverridesProvider value={{ actions, columns, sections, components, modals, customDataSources }}>
|
|
2224
|
+
<PatternsWizardOverridesProvider value={{ actions, columns, slots, sections, components, modals, customDataSources }}>
|
|
2207
2225
|
<AutoPatternsApp configuration={config} />
|
|
2208
2226
|
</PatternsWizardOverridesProvider>
|
|
2209
2227
|
);
|
|
@@ -2212,12 +2230,13 @@ export default function YourPage() {
|
|
|
2212
2230
|
|
|
2213
2231
|
### Important: Updating Hook Index Files
|
|
2214
2232
|
|
|
2215
|
-
**When adding any new implementation (action, modal, column, section or component), you MUST update the corresponding hook in the `index.tsx` file to include your new implementation.** The main page component uses these hooks, so they serve as the central export point for each type of override.
|
|
2233
|
+
**When adding any new implementation (action, modal, column, slot, section or component), you MUST update the corresponding hook in the `index.tsx` file to include your new implementation.** The main page component uses these hooks, so they serve as the central export point for each type of override.
|
|
2216
2234
|
|
|
2217
2235
|
For example:
|
|
2218
2236
|
- Adding a new action → Update `../components/actions/index.tsx` to include the new action in the `useActions` hook
|
|
2219
2237
|
- Adding a new modal → Update `../components/modals/index.tsx` to include the new modal in the `useModals` hook
|
|
2220
2238
|
- Adding a new column override → Update `../components/columns/index.tsx` to include the new column in the `useColumns` hook
|
|
2239
|
+
- Adding a new slot component → Update `../components/slots/index.tsx` to include the new slot in the `useSlots` hook
|
|
2221
2240
|
- Adding a new section renderer → Update `../components/sections/index.tsx` to include the new section in the `useSections` hook
|
|
2222
2241
|
- Adding a new custom component → Update `../components/customComponents/index.tsx` to include the new component in the `useComponents` hook
|
|
2223
2242
|
- Adding a new custom data source → Update `../components/customDataSources/index.tsx` to include the new data source in the `useCustomDataSources` hook
|
|
@@ -2947,6 +2966,10 @@ interface Section {
|
|
|
2947
2966
|
prefixIcon?: React.ReactElement;
|
|
2948
2967
|
onClick: () => void;
|
|
2949
2968
|
};
|
|
2969
|
+
badge?: {
|
|
2970
|
+
visible: boolean;
|
|
2971
|
+
skin?: 'light' | 'danger' | 'neutralLight';
|
|
2972
|
+
};
|
|
2950
2973
|
}
|
|
2951
2974
|
```
|
|
2952
2975
|
|
|
@@ -2954,6 +2977,7 @@ The section renderer receives an item and returns:
|
|
|
2954
2977
|
- **id**: A unique identifier for the section (items with the same id are grouped together)
|
|
2955
2978
|
- **title**: The text displayed in the section header
|
|
2956
2979
|
- **primaryAction** (optional): An action button displayed in the section header
|
|
2980
|
+
- **badge** (optional): A badge configuration displayed in the section header
|
|
2957
2981
|
|
|
2958
2982
|
#### Example: Section Renderer Implementation
|
|
2959
2983
|
|
|
@@ -2979,6 +3003,10 @@ export function groupByType(item: any): Section {
|
|
|
2979
3003
|
console.log(`Showing all ${petType}s`);
|
|
2980
3004
|
},
|
|
2981
3005
|
},
|
|
3006
|
+
badge: {
|
|
3007
|
+
visible: true,
|
|
3008
|
+
skin: 'light',
|
|
3009
|
+
},
|
|
2982
3010
|
};
|
|
2983
3011
|
}
|
|
2984
3012
|
```
|
|
@@ -3001,16 +3029,20 @@ export function groupByAgeAndVaccination(item: any): Section {
|
|
|
3001
3029
|
|
|
3002
3030
|
let sectionId: string;
|
|
3003
3031
|
let sectionTitle: string;
|
|
3032
|
+
let badgeSkin: 'light' | 'danger' | 'neutralLight' = 'light';
|
|
3004
3033
|
|
|
3005
3034
|
if (age < 1) {
|
|
3006
3035
|
sectionId = 'puppies';
|
|
3007
3036
|
sectionTitle = 'Puppies (Under 1 year)';
|
|
3037
|
+
badgeSkin = 'neutralLight';
|
|
3008
3038
|
} else if (age >= 1 && age <= 5) {
|
|
3009
3039
|
sectionId = isVaccinated ? 'young-vaccinated' : 'young-unvaccinated';
|
|
3010
3040
|
sectionTitle = `Young Adults (1-5 years) - ${isVaccinated ? 'Vaccinated' : 'Not Vaccinated'}`;
|
|
3041
|
+
badgeSkin = isVaccinated ? 'light' : 'danger';
|
|
3011
3042
|
} else {
|
|
3012
3043
|
sectionId = 'seniors';
|
|
3013
3044
|
sectionTitle = 'Senior Pets (5+ years)';
|
|
3045
|
+
badgeSkin = 'light';
|
|
3014
3046
|
}
|
|
3015
3047
|
|
|
3016
3048
|
return {
|
|
@@ -3023,6 +3055,10 @@ export function groupByAgeAndVaccination(item: any): Section {
|
|
|
3023
3055
|
// Show special care information for puppies
|
|
3024
3056
|
},
|
|
3025
3057
|
} : undefined,
|
|
3058
|
+
badge: {
|
|
3059
|
+
visible: true,
|
|
3060
|
+
skin: badgeSkin,
|
|
3061
|
+
},
|
|
3026
3062
|
};
|
|
3027
3063
|
}
|
|
3028
3064
|
```
|
|
@@ -3051,4 +3087,156 @@ import * as actions from './components/actions';
|
|
|
3051
3087
|
|
|
3052
3088
|
By implementing sections, you can significantly improve the user experience when dealing with large datasets by providing logical groupings that make information easier to find and understand.
|
|
3053
3089
|
|
|
3090
|
+
## Slots
|
|
3091
|
+
|
|
3092
|
+
Slots allow you to inject custom React components into collection pages at specific points in the component hierarchy. Unlike other overrides that modify existing functionality, slots enable you to add entirely custom UI elements anywhere within the collection page components array.
|
|
3093
|
+
|
|
3094
|
+
Slots are useful for:
|
|
3095
|
+
- Adding custom banners or announcements above or below the table/grid
|
|
3096
|
+
- Inserting analytics widgets or dashboards
|
|
3097
|
+
- Adding custom promotional content
|
|
3098
|
+
- Implementing page-specific functionality that doesn't fit into standard patterns
|
|
3099
|
+
|
|
3100
|
+
### Configuration Structure
|
|
3101
|
+
|
|
3102
|
+
Slots are configured in the collection page configuration using the `CustomComponentConfig` structure:
|
|
3103
|
+
|
|
3104
|
+
```json
|
|
3105
|
+
{
|
|
3106
|
+
"type": "custom",
|
|
3107
|
+
"id": "myCustomSlot"
|
|
3108
|
+
}
|
|
3109
|
+
```
|
|
3110
|
+
|
|
3111
|
+
**Key Properties:**
|
|
3112
|
+
- `type`: Must be set to `"custom"` to identify this as a slot component
|
|
3113
|
+
- `id`: A unique identifier that maps to your slot component implementation
|
|
3114
|
+
|
|
3115
|
+
### Component Positioning
|
|
3116
|
+
|
|
3117
|
+
Slot components can be positioned anywhere within the `components` array of a collection page. They will be rendered in the exact order specified in the configuration:
|
|
3118
|
+
|
|
3119
|
+
```json
|
|
3120
|
+
{
|
|
3121
|
+
"type": "collectionPage",
|
|
3122
|
+
"collectionPage": {
|
|
3123
|
+
"components": [
|
|
3124
|
+
{
|
|
3125
|
+
"type": "custom",
|
|
3126
|
+
"id": "topBanner"
|
|
3127
|
+
},
|
|
3128
|
+
{
|
|
3129
|
+
"type": "collection",
|
|
3130
|
+
"collection": {
|
|
3131
|
+
"collectionId": "MyCollection"
|
|
3132
|
+
},
|
|
3133
|
+
"layout": [...]
|
|
3134
|
+
},
|
|
3135
|
+
{
|
|
3136
|
+
"type": "custom",
|
|
3137
|
+
"id": "bottomStats"
|
|
3138
|
+
}
|
|
3139
|
+
]
|
|
3140
|
+
}
|
|
3141
|
+
}
|
|
3142
|
+
```
|
|
3143
|
+
|
|
3144
|
+
This configuration will render:
|
|
3145
|
+
1. The custom `topBanner` component at the top
|
|
3146
|
+
2. The main collection component (table/grid) in the middle
|
|
3147
|
+
3. The custom `bottomStats` component at the bottom
|
|
3148
|
+
|
|
3149
|
+
### Implementation Structure
|
|
3150
|
+
|
|
3151
|
+
#### Creating Slot Components
|
|
3152
|
+
|
|
3153
|
+
Slot components are standard React functional components that take no props:
|
|
3154
|
+
|
|
3155
|
+
```tsx
|
|
3156
|
+
import React from 'react';
|
|
3157
|
+
import { Box, Card, Text, Button } from '@wix/design-system';
|
|
3158
|
+
|
|
3159
|
+
export const TopBannerComponent: React.FC = () => {
|
|
3160
|
+
return (
|
|
3161
|
+
<Card>
|
|
3162
|
+
<Card.Content>
|
|
3163
|
+
<Box direction="vertical" gap={2}>
|
|
3164
|
+
<Text size="large" weight="bold">Welcome to Pet Management</Text>
|
|
3165
|
+
<Text>Manage all your pets from this central dashboard.</Text>
|
|
3166
|
+
<Button size="small">Get Started</Button>
|
|
3167
|
+
</Box>
|
|
3168
|
+
</Card.Content>
|
|
3169
|
+
</Card>
|
|
3170
|
+
);
|
|
3171
|
+
};
|
|
3172
|
+
|
|
3173
|
+
export const BottomStatsComponent: React.FC = () => {
|
|
3174
|
+
return (
|
|
3175
|
+
<Card>
|
|
3176
|
+
<Card.Content>
|
|
3177
|
+
<Box direction="horizontal" gap={4}>
|
|
3178
|
+
<Box direction="vertical" gap={1}>
|
|
3179
|
+
<Text size="large" weight="bold">47</Text>
|
|
3180
|
+
<Text size="small">Total Pets</Text>
|
|
3181
|
+
</Box>
|
|
3182
|
+
<Box direction="vertical" gap={1}>
|
|
3183
|
+
<Text size="large" weight="bold">12</Text>
|
|
3184
|
+
<Text size="small">Available for Adoption</Text>
|
|
3185
|
+
</Box>
|
|
3186
|
+
</Box>
|
|
3187
|
+
</Card.Content>
|
|
3188
|
+
</Card>
|
|
3189
|
+
);
|
|
3190
|
+
};
|
|
3191
|
+
```
|
|
3192
|
+
|
|
3193
|
+
#### Creating the Slots Hook
|
|
3194
|
+
|
|
3195
|
+
In `components/slots/index.tsx`:
|
|
3196
|
+
|
|
3197
|
+
```tsx
|
|
3198
|
+
import { TopBannerComponent } from './TopBannerComponent';
|
|
3199
|
+
import { BottomStatsComponent } from './BottomStatsComponent';
|
|
3200
|
+
|
|
3201
|
+
export const useSlots = () => {
|
|
3202
|
+
// You can access React context and other hooks here
|
|
3203
|
+
return {
|
|
3204
|
+
topBanner: TopBannerComponent,
|
|
3205
|
+
bottomStats: BottomStatsComponent
|
|
3206
|
+
};
|
|
3207
|
+
};
|
|
3208
|
+
```
|
|
3209
|
+
|
|
3210
|
+
**Important:** Every time you create a new slot component, you must import it and add it to the `useSlots` hook return object. The key in the return object must match the `id` specified in your JSON configuration.
|
|
3211
|
+
|
|
3212
|
+
#### Registering Slots in Your Page
|
|
3213
|
+
|
|
3214
|
+
In your main page component:
|
|
3215
|
+
|
|
3216
|
+
```tsx
|
|
3217
|
+
import { useSlots } from '../components/slots';
|
|
3218
|
+
|
|
3219
|
+
export default function YourPage() {
|
|
3220
|
+
const slots = useSlots();
|
|
3221
|
+
|
|
3222
|
+
return (
|
|
3223
|
+
<PatternsWizardOverridesProvider value={{ slots }}>
|
|
3224
|
+
<AutoPatternsApp configuration={config} />
|
|
3225
|
+
</PatternsWizardOverridesProvider>
|
|
3226
|
+
);
|
|
3227
|
+
}
|
|
3228
|
+
```
|
|
3229
|
+
|
|
3230
|
+
### Important Guidelines for Slots
|
|
3231
|
+
|
|
3232
|
+
1. **Component Signature**: Slot components must be React functional components with no props: `React.FC`
|
|
3233
|
+
2. **Rendering Order**: Components render in the exact order specified in the `components` array
|
|
3234
|
+
3. **Performance**: Slot components re-render with the page, so optimize for performance if needed
|
|
3235
|
+
4. **Styling**: Follow the design system patterns and responsive design principles
|
|
3236
|
+
|
|
3237
|
+
|
|
3238
|
+
**Important:** Every time you create a new slot component, you must import it and add it to the `useSlots` hook return object in the `./components/slots/index.tsx` file. The key must match the `id` specified in your JSON configuration.
|
|
3239
|
+
|
|
3240
|
+
Slots provide a powerful way to enhance collection pages with custom functionality while maintaining the structure and features of the AutoPatterns system.
|
|
3241
|
+
|
|
3054
3242
|
---
|
|
@@ -28,6 +28,10 @@ your-page/
|
|
|
28
28
|
│ ├── index.tsx // Exports useColumns hook
|
|
29
29
|
│ ├── name.ts
|
|
30
30
|
│ └── date.ts
|
|
31
|
+
├── slots/ // Custom slot components for collection pages
|
|
32
|
+
│ ├── index.tsx // Exports useSlots hook
|
|
33
|
+
│ ├── TopBannerComponent.tsx
|
|
34
|
+
│ └── BottomStatsComponent.tsx
|
|
31
35
|
├── customComponents/ // Custom entity page components
|
|
32
36
|
│ ├── index.tsx // Exports useComponents hook
|
|
33
37
|
│ ├── CustomNameField.tsx
|
|
@@ -35,16 +39,12 @@ your-page/
|
|
|
35
39
|
├── modals/ // Custom modals
|
|
36
40
|
│ ├── index.tsx // Exports useModals hook
|
|
37
41
|
│ └── myCustomModal.tsx
|
|
38
|
-
|
|
42
|
+
├── customDataSources/ // Custom data sources
|
|
39
43
|
│ ├── index.tsx // Exports useCustomDataSources hook
|
|
40
44
|
│ └── myCustomDataSource.ts
|
|
41
|
-
|
|
42
|
-
│ ├── index.tsx
|
|
43
|
-
│ └── groupByType.ts
|
|
44
|
-
└── customComponents/ // Custom entity page components
|
|
45
|
+
└── sections/ // Section renderers
|
|
45
46
|
├── index.tsx
|
|
46
|
-
|
|
47
|
-
└── InfoCard.tsx
|
|
47
|
+
└── groupByType.ts
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
### Using Override Hooks in Your Page
|
|
@@ -54,6 +54,7 @@ In your page component, use the hook-based approach to access React context and
|
|
|
54
54
|
```tsx
|
|
55
55
|
import { useActions } from '../components/actions';
|
|
56
56
|
import { useColumns } from '../components/columns';
|
|
57
|
+
import { useSlots } from '../components/slots';
|
|
57
58
|
import { useSections } from '../components/sections';
|
|
58
59
|
import { useComponents } from '../components/customComponents';
|
|
59
60
|
import { useModals } from '../components/modals';
|
|
@@ -62,13 +63,14 @@ import { useCustomDataSources } from '../components/customDataSources';
|
|
|
62
63
|
export default function YourPage() {
|
|
63
64
|
const actions = useActions();
|
|
64
65
|
const columns = useColumns();
|
|
66
|
+
const slots = useSlots();
|
|
65
67
|
const sections = useSections();
|
|
66
68
|
const components = useComponents();
|
|
67
69
|
const modals = useModals();
|
|
68
70
|
const customDataSources = useCustomDataSources();
|
|
69
71
|
|
|
70
72
|
return (
|
|
71
|
-
<PatternsWizardOverridesProvider value={{ actions, columns, sections, components, modals, customDataSources }}>
|
|
73
|
+
<PatternsWizardOverridesProvider value={{ actions, columns, slots, sections, components, modals, customDataSources }}>
|
|
72
74
|
<AutoPatternsApp configuration={config} />
|
|
73
75
|
</PatternsWizardOverridesProvider>
|
|
74
76
|
);
|
|
@@ -77,12 +79,13 @@ export default function YourPage() {
|
|
|
77
79
|
|
|
78
80
|
### Important: Updating Hook Index Files
|
|
79
81
|
|
|
80
|
-
**When adding any new implementation (action, modal, column, section or component), you MUST update the corresponding hook in the `index.tsx` file to include your new implementation.** The main page component uses these hooks, so they serve as the central export point for each type of override.
|
|
82
|
+
**When adding any new implementation (action, modal, column, slot, section or component), you MUST update the corresponding hook in the `index.tsx` file to include your new implementation.** The main page component uses these hooks, so they serve as the central export point for each type of override.
|
|
81
83
|
|
|
82
84
|
For example:
|
|
83
85
|
- Adding a new action → Update `../components/actions/index.tsx` to include the new action in the `useActions` hook
|
|
84
86
|
- Adding a new modal → Update `../components/modals/index.tsx` to include the new modal in the `useModals` hook
|
|
85
87
|
- Adding a new column override → Update `../components/columns/index.tsx` to include the new column in the `useColumns` hook
|
|
88
|
+
- Adding a new slot component → Update `../components/slots/index.tsx` to include the new slot in the `useSlots` hook
|
|
86
89
|
- Adding a new section renderer → Update `../components/sections/index.tsx` to include the new section in the `useSections` hook
|
|
87
90
|
- Adding a new custom component → Update `../components/customComponents/index.tsx` to include the new component in the `useComponents` hook
|
|
88
91
|
- Adding a new custom data source → Update `../components/customDataSources/index.tsx` to include the new data source in the `useCustomDataSources` hook
|
|
@@ -812,6 +815,10 @@ interface Section {
|
|
|
812
815
|
prefixIcon?: React.ReactElement;
|
|
813
816
|
onClick: () => void;
|
|
814
817
|
};
|
|
818
|
+
badge?: {
|
|
819
|
+
visible: boolean;
|
|
820
|
+
skin?: 'light' | 'danger' | 'neutralLight';
|
|
821
|
+
};
|
|
815
822
|
}
|
|
816
823
|
```
|
|
817
824
|
|
|
@@ -819,6 +826,7 @@ The section renderer receives an item and returns:
|
|
|
819
826
|
- **id**: A unique identifier for the section (items with the same id are grouped together)
|
|
820
827
|
- **title**: The text displayed in the section header
|
|
821
828
|
- **primaryAction** (optional): An action button displayed in the section header
|
|
829
|
+
- **badge** (optional): A badge configuration displayed in the section header
|
|
822
830
|
|
|
823
831
|
#### Example: Section Renderer Implementation
|
|
824
832
|
|
|
@@ -844,6 +852,10 @@ export function groupByType(item: any): Section {
|
|
|
844
852
|
console.log(`Showing all ${petType}s`);
|
|
845
853
|
},
|
|
846
854
|
},
|
|
855
|
+
badge: {
|
|
856
|
+
visible: true,
|
|
857
|
+
skin: 'light',
|
|
858
|
+
},
|
|
847
859
|
};
|
|
848
860
|
}
|
|
849
861
|
```
|
|
@@ -866,16 +878,20 @@ export function groupByAgeAndVaccination(item: any): Section {
|
|
|
866
878
|
|
|
867
879
|
let sectionId: string;
|
|
868
880
|
let sectionTitle: string;
|
|
881
|
+
let badgeSkin: 'light' | 'danger' | 'neutralLight' = 'light';
|
|
869
882
|
|
|
870
883
|
if (age < 1) {
|
|
871
884
|
sectionId = 'puppies';
|
|
872
885
|
sectionTitle = 'Puppies (Under 1 year)';
|
|
886
|
+
badgeSkin = 'neutralLight';
|
|
873
887
|
} else if (age >= 1 && age <= 5) {
|
|
874
888
|
sectionId = isVaccinated ? 'young-vaccinated' : 'young-unvaccinated';
|
|
875
889
|
sectionTitle = `Young Adults (1-5 years) - ${isVaccinated ? 'Vaccinated' : 'Not Vaccinated'}`;
|
|
890
|
+
badgeSkin = isVaccinated ? 'light' : 'danger';
|
|
876
891
|
} else {
|
|
877
892
|
sectionId = 'seniors';
|
|
878
893
|
sectionTitle = 'Senior Pets (5+ years)';
|
|
894
|
+
badgeSkin = 'light';
|
|
879
895
|
}
|
|
880
896
|
|
|
881
897
|
return {
|
|
@@ -888,6 +904,10 @@ export function groupByAgeAndVaccination(item: any): Section {
|
|
|
888
904
|
// Show special care information for puppies
|
|
889
905
|
},
|
|
890
906
|
} : undefined,
|
|
907
|
+
badge: {
|
|
908
|
+
visible: true,
|
|
909
|
+
skin: badgeSkin,
|
|
910
|
+
},
|
|
891
911
|
};
|
|
892
912
|
}
|
|
893
913
|
```
|
|
@@ -915,3 +935,155 @@ import * as actions from './components/actions';
|
|
|
915
935
|
|
|
916
936
|
|
|
917
937
|
By implementing sections, you can significantly improve the user experience when dealing with large datasets by providing logical groupings that make information easier to find and understand.
|
|
938
|
+
|
|
939
|
+
## Slots
|
|
940
|
+
|
|
941
|
+
Slots allow you to inject custom React components into collection pages at specific points in the component hierarchy. Unlike other overrides that modify existing functionality, slots enable you to add entirely custom UI elements anywhere within the collection page components array.
|
|
942
|
+
|
|
943
|
+
Slots are useful for:
|
|
944
|
+
- Adding custom banners or announcements above or below the table/grid
|
|
945
|
+
- Inserting analytics widgets or dashboards
|
|
946
|
+
- Adding custom promotional content
|
|
947
|
+
- Implementing page-specific functionality that doesn't fit into standard patterns
|
|
948
|
+
|
|
949
|
+
### Configuration Structure
|
|
950
|
+
|
|
951
|
+
Slots are configured in the collection page configuration using the `CustomComponentConfig` structure:
|
|
952
|
+
|
|
953
|
+
```json
|
|
954
|
+
{
|
|
955
|
+
"type": "custom",
|
|
956
|
+
"id": "myCustomSlot"
|
|
957
|
+
}
|
|
958
|
+
```
|
|
959
|
+
|
|
960
|
+
**Key Properties:**
|
|
961
|
+
- `type`: Must be set to `"custom"` to identify this as a slot component
|
|
962
|
+
- `id`: A unique identifier that maps to your slot component implementation
|
|
963
|
+
|
|
964
|
+
### Component Positioning
|
|
965
|
+
|
|
966
|
+
Slot components can be positioned anywhere within the `components` array of a collection page. They will be rendered in the exact order specified in the configuration:
|
|
967
|
+
|
|
968
|
+
```json
|
|
969
|
+
{
|
|
970
|
+
"type": "collectionPage",
|
|
971
|
+
"collectionPage": {
|
|
972
|
+
"components": [
|
|
973
|
+
{
|
|
974
|
+
"type": "custom",
|
|
975
|
+
"id": "topBanner"
|
|
976
|
+
},
|
|
977
|
+
{
|
|
978
|
+
"type": "collection",
|
|
979
|
+
"collection": {
|
|
980
|
+
"collectionId": "MyCollection"
|
|
981
|
+
},
|
|
982
|
+
"layout": [...]
|
|
983
|
+
},
|
|
984
|
+
{
|
|
985
|
+
"type": "custom",
|
|
986
|
+
"id": "bottomStats"
|
|
987
|
+
}
|
|
988
|
+
]
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
```
|
|
992
|
+
|
|
993
|
+
This configuration will render:
|
|
994
|
+
1. The custom `topBanner` component at the top
|
|
995
|
+
2. The main collection component (table/grid) in the middle
|
|
996
|
+
3. The custom `bottomStats` component at the bottom
|
|
997
|
+
|
|
998
|
+
### Implementation Structure
|
|
999
|
+
|
|
1000
|
+
#### Creating Slot Components
|
|
1001
|
+
|
|
1002
|
+
Slot components are standard React functional components that take no props:
|
|
1003
|
+
|
|
1004
|
+
```tsx
|
|
1005
|
+
import React from 'react';
|
|
1006
|
+
import { Box, Card, Text, Button } from '@wix/design-system';
|
|
1007
|
+
|
|
1008
|
+
export const TopBannerComponent: React.FC = () => {
|
|
1009
|
+
return (
|
|
1010
|
+
<Card>
|
|
1011
|
+
<Card.Content>
|
|
1012
|
+
<Box direction="vertical" gap={2}>
|
|
1013
|
+
<Text size="large" weight="bold">Welcome to Pet Management</Text>
|
|
1014
|
+
<Text>Manage all your pets from this central dashboard.</Text>
|
|
1015
|
+
<Button size="small">Get Started</Button>
|
|
1016
|
+
</Box>
|
|
1017
|
+
</Card.Content>
|
|
1018
|
+
</Card>
|
|
1019
|
+
);
|
|
1020
|
+
};
|
|
1021
|
+
|
|
1022
|
+
export const BottomStatsComponent: React.FC = () => {
|
|
1023
|
+
return (
|
|
1024
|
+
<Card>
|
|
1025
|
+
<Card.Content>
|
|
1026
|
+
<Box direction="horizontal" gap={4}>
|
|
1027
|
+
<Box direction="vertical" gap={1}>
|
|
1028
|
+
<Text size="large" weight="bold">47</Text>
|
|
1029
|
+
<Text size="small">Total Pets</Text>
|
|
1030
|
+
</Box>
|
|
1031
|
+
<Box direction="vertical" gap={1}>
|
|
1032
|
+
<Text size="large" weight="bold">12</Text>
|
|
1033
|
+
<Text size="small">Available for Adoption</Text>
|
|
1034
|
+
</Box>
|
|
1035
|
+
</Box>
|
|
1036
|
+
</Card.Content>
|
|
1037
|
+
</Card>
|
|
1038
|
+
);
|
|
1039
|
+
};
|
|
1040
|
+
```
|
|
1041
|
+
|
|
1042
|
+
#### Creating the Slots Hook
|
|
1043
|
+
|
|
1044
|
+
In `components/slots/index.tsx`:
|
|
1045
|
+
|
|
1046
|
+
```tsx
|
|
1047
|
+
import { TopBannerComponent } from './TopBannerComponent';
|
|
1048
|
+
import { BottomStatsComponent } from './BottomStatsComponent';
|
|
1049
|
+
|
|
1050
|
+
export const useSlots = () => {
|
|
1051
|
+
// You can access React context and other hooks here
|
|
1052
|
+
return {
|
|
1053
|
+
topBanner: TopBannerComponent,
|
|
1054
|
+
bottomStats: BottomStatsComponent
|
|
1055
|
+
};
|
|
1056
|
+
};
|
|
1057
|
+
```
|
|
1058
|
+
|
|
1059
|
+
**Important:** Every time you create a new slot component, you must import it and add it to the `useSlots` hook return object. The key in the return object must match the `id` specified in your JSON configuration.
|
|
1060
|
+
|
|
1061
|
+
#### Registering Slots in Your Page
|
|
1062
|
+
|
|
1063
|
+
In your main page component:
|
|
1064
|
+
|
|
1065
|
+
```tsx
|
|
1066
|
+
import { useSlots } from '../components/slots';
|
|
1067
|
+
|
|
1068
|
+
export default function YourPage() {
|
|
1069
|
+
const slots = useSlots();
|
|
1070
|
+
|
|
1071
|
+
return (
|
|
1072
|
+
<PatternsWizardOverridesProvider value={{ slots }}>
|
|
1073
|
+
<AutoPatternsApp configuration={config} />
|
|
1074
|
+
</PatternsWizardOverridesProvider>
|
|
1075
|
+
);
|
|
1076
|
+
}
|
|
1077
|
+
```
|
|
1078
|
+
|
|
1079
|
+
### Important Guidelines for Slots
|
|
1080
|
+
|
|
1081
|
+
1. **Component Signature**: Slot components must be React functional components with no props: `React.FC`
|
|
1082
|
+
2. **Rendering Order**: Components render in the exact order specified in the `components` array
|
|
1083
|
+
3. **Performance**: Slot components re-render with the page, so optimize for performance if needed
|
|
1084
|
+
4. **Styling**: Follow the design system patterns and responsive design principles
|
|
1085
|
+
|
|
1086
|
+
|
|
1087
|
+
**Important:** Every time you create a new slot component, you must import it and add it to the `useSlots` hook return object in the `./components/slots/index.tsx` file. The key must match the `id` specified in your JSON configuration.
|
|
1088
|
+
|
|
1089
|
+
Slots provide a powerful way to enhance collection pages with custom functionality while maintaining the structure and features of the AutoPatterns system.
|