@carto/meridian-ds 3.0.2 → 3.0.3-alpha.b8efbf0.253
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/CHANGELOG.md +2 -0
- package/README.md +34 -0
- package/dist/bin/meridian-ds-mcp.js +269 -0
- package/dist/metadata.json +723 -0
- package/dist/types/components/Autocomplete/Autocomplete/Autocomplete.d.ts +1 -0
- package/dist/types/components/Autocomplete/Autocomplete/Autocomplete.d.ts.map +1 -1
- package/dist/types/components/Autocomplete/Autocomplete/Autocomplete.metadata.d.ts +26 -0
- package/dist/types/components/Autocomplete/Autocomplete/Autocomplete.metadata.d.ts.map +1 -0
- package/dist/types/components/Autocomplete/Autocomplete/Autocomplete.stories.d.ts.map +1 -1
- package/dist/types/components/Autocomplete/types.d.ts +2 -1
- package/dist/types/components/Autocomplete/types.d.ts.map +1 -1
- package/dist/types/components/Button/Button.d.ts +8 -0
- package/dist/types/components/Button/Button.d.ts.map +1 -1
- package/dist/types/components/Button/Button.metadata.d.ts +26 -0
- package/dist/types/components/Button/Button.metadata.d.ts.map +1 -0
- package/dist/types/components/Dialog/Dialog/Dialog.d.ts +1 -0
- package/dist/types/components/Dialog/Dialog/Dialog.d.ts.map +1 -1
- package/dist/types/components/Dialog/Dialog/Dialog.metadata.d.ts +26 -0
- package/dist/types/components/Dialog/Dialog/Dialog.metadata.d.ts.map +1 -0
- package/dist/types/components/Dialog/types.d.ts +3 -8
- package/dist/types/components/Dialog/types.d.ts.map +1 -1
- package/dist/types/components/IconButton/IconButton.d.ts +39 -4
- package/dist/types/components/IconButton/IconButton.d.ts.map +1 -1
- package/dist/types/components/IconButton/IconButton.metadata.d.ts +15 -0
- package/dist/types/components/IconButton/IconButton.metadata.d.ts.map +1 -0
- package/dist/types/components/IconButton/IconButton.stories.d.ts +13 -0
- package/dist/types/components/IconButton/IconButton.stories.d.ts.map +1 -1
- package/dist/types/components/SelectField/SelectField/SelectField.d.ts +1 -0
- package/dist/types/components/SelectField/SelectField/SelectField.d.ts.map +1 -1
- package/dist/types/components/SelectField/SelectField/SelectField.metadata.d.ts +26 -0
- package/dist/types/components/SelectField/SelectField/SelectField.metadata.d.ts.map +1 -0
- package/dist/types/components/SelectField/SelectField/SelectField.stories.d.ts.map +1 -1
- package/dist/types/components/SelectField/types.d.ts +6 -0
- package/dist/types/components/SelectField/types.d.ts.map +1 -1
- package/dist/types/components/SplitButton/SplitButton.d.ts +27 -0
- package/dist/types/components/SplitButton/SplitButton.d.ts.map +1 -1
- package/dist/types/components/SplitButton/SplitButton.metadata.d.ts +15 -0
- package/dist/types/components/SplitButton/SplitButton.metadata.d.ts.map +1 -0
- package/dist/types/components/Tag/Tag.d.ts +2 -1
- package/dist/types/components/Tag/Tag.d.ts.map +1 -1
- package/dist/types/components/Tag/Tag.metadata.d.ts +18 -0
- package/dist/types/components/Tag/Tag.metadata.d.ts.map +1 -0
- package/dist/types/components/Typography/Typography.d.ts +3 -0
- package/dist/types/components/Typography/Typography.d.ts.map +1 -1
- package/dist/types/components/Typography/Typography.metadata.d.ts +26 -0
- package/dist/types/components/Typography/Typography.metadata.d.ts.map +1 -0
- package/package.json +12 -3
|
@@ -0,0 +1,723 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"version": "3.0.3-alpha.b8efbf0.253",
|
|
4
|
+
"conventions": "# Meridian usage conventions (for code-generating agents)\n\nSystem-level rules an agent should apply across all components. These are the\ncross-cutting opinions that don't belong to any single component, so they live\nhere once instead of being copied into every component's metadata.\n\nMeridian is the source of truth: when an existing codebase pattern contradicts Meridian, follow Meridian — don't replicate the contradicting local pattern.\n\n## Choosing a component\n\n- Don't hand-roll what the design system already provides. Before writing a\n custom component, a styled wrapper, or a block of primitives (a modal,\n chip/tag, card, empty state, dropdown, tooltip, copy-to-clipboard input,\n etc.), confirm no Meridian component covers it — reuse or extend the existing one instead of rebuilding it.\n- Prefer a Meridian component over a bare MUI one whenever a Meridian wrapper\n exists — the wrappers carry CARTO theming, a11y defaults, and narrowed APIs.\n- Resolve \"which component\" by reading each one's `description` + `keywords`,\n then confirm with its `decisionTree` (the conditions that point elsewhere).\n Don't infer selection from prop lists.\n\n## Icons\n\n- Source icons from Meridian's custom-icons first, then `@mui/icons-material`; add a local SVG only when neither has an equivalent. Don't duplicate an icon the design system already ships.\n\n## Accessibility\n\n- Any icon-only control needs an accessible name: `tooltip` or `aria-label`.\n- Don't disable a control without telling the user why — pair a disabled action with a tooltip explaining the requirement.\n- An `aria-label` must be human-readable text describing the control, not a test id in disguise — use a separate test hook for that.\n- User-facing strings (labels, `aria-label`, placeholders, messages) go through the app's i18n layer, not hardcoded literals.\n\n## Props\n\n- Exact props, types, and JSDoc come from the package's type declarations —\n `import` the component and let your IDE/tsc show the signature. Don't guess a prop name; the compiler validates it.\n- A component's curation lists the high-value inherited MUI props worth knowing (`curation.mui`, e.g. `color`/`variant`/`size`); the rest of MUI's surface is available but rarely needed.\n- Never pass `sx`/inline styles to restyle a component; use its documented props and the theme tokens.\n\n## Styling\n\n- Use theme tokens, never hardcoded values: colors from the palette (`text.*`, `background.*`, `divider`, semantic `*.main`) and spacing from the theme spacing scale — no raw hex/rgb or pixel literals for color or spacing.\n- Text uses `<Typography variant=…>` (with the `weight` prop for emphasis), never hardcoded `fontSize`/`fontWeight`/`lineHeight`/`fontFamily`.\n- Use `sx` for one-off styling, not the deprecated MUI system props\n (`<Box px={2}>` → `<Box sx={{ px: 2 }}>`).\n\n## Examples\n\n- Never invent example code when a story exists — use the component's real story source (`meridian_get_examples`).\n",
|
|
5
|
+
"components": [
|
|
6
|
+
{
|
|
7
|
+
"name": "Autocomplete",
|
|
8
|
+
"description": "Searchable single-select input that suggests options as the user types; use for selecting one value from a large list (10+ items, e.g. columns, datasets, users). Supports async loading state and virtualized rendering for very long lists.",
|
|
9
|
+
"curation": {
|
|
10
|
+
"keywords": [
|
|
11
|
+
"combobox",
|
|
12
|
+
"typeahead",
|
|
13
|
+
"search select",
|
|
14
|
+
"dropdown search",
|
|
15
|
+
"choose from list"
|
|
16
|
+
],
|
|
17
|
+
"mui": [
|
|
18
|
+
{
|
|
19
|
+
"name": "options",
|
|
20
|
+
"aiHint": "Generic type T - can be strings, objects, or any data type. Use getOptionLabel to extract display text from objects."
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "value",
|
|
24
|
+
"aiHint": "Always pass an explicit value (or null for cleared state); leaving it undefined causes MUI to switch between controlled and uncontrolled modes."
|
|
25
|
+
},
|
|
26
|
+
"onChange",
|
|
27
|
+
{
|
|
28
|
+
"name": "getOptionLabel",
|
|
29
|
+
"aiHint": "If users need to search across multiple fields (e.g., name, email, role) but getOptionLabel returns only one, provide a custom filterOptions function that matches across all relevant fields - the default filter only inspects the getOptionLabel return value."
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "open",
|
|
33
|
+
"aiHint": "For a large option set, keep the list closed until the user types (require search) rather than showing everything on focus; for a short set, opening immediately is fine."
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "renderInput",
|
|
37
|
+
"aiHint": "Must spread params to TextField. Use for adding labels, placeholders, and helper text. Pass InputLabelProps={{ shrink: true }} to keep the label shrunk."
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "renderOption",
|
|
41
|
+
"aiHint": "Use MenuItem or ListItemButton for proper styling. Spread props to the root element."
|
|
42
|
+
},
|
|
43
|
+
"disabled",
|
|
44
|
+
"size"
|
|
45
|
+
],
|
|
46
|
+
"decisionTree": [
|
|
47
|
+
{
|
|
48
|
+
"condition": "Binary yes/no or on/off choice",
|
|
49
|
+
"use": "Checkbox",
|
|
50
|
+
"isMUI": true,
|
|
51
|
+
"aiHint": "Use Switch instead when toggling a live setting"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"condition": "<10 items and no search needed",
|
|
55
|
+
"use": "SelectField"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"condition": "Multiple selection",
|
|
59
|
+
"use": "MultipleAutocomplete"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"condition": "User-created options",
|
|
63
|
+
"use": "CreatableAutocomplete"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"condition": "User/group selection with grouping",
|
|
67
|
+
"use": "MultipleAutocomplete",
|
|
68
|
+
"aiHint": "Use createAutocompleteGroupByList utility to group options"
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
},
|
|
72
|
+
"examples": [
|
|
73
|
+
{
|
|
74
|
+
"name": "Playground",
|
|
75
|
+
"id": "components-autocomplete-autocomplete--playground",
|
|
76
|
+
"code": "import { Autocomplete, AutocompleteProps } from '@carto/meridian-ds/components'\nimport { useState } from 'react'\n\nconst top100Films = getTop100Films()\n\nconst Playground = ({\n label,\n variant,\n placeholder,\n helperText,\n error,\n size,\n required,\n disableCloseOnSelect,\n ...props\n}: AutocompleteProps<(typeof top100Films)[number], boolean> &\n AutocompleteInputProps) => {\n const [value, setValue] = useState<StorybookFilmProps | null>(null)\n\n return (\n <Autocomplete\n {...props}\n value={value}\n onChange={(ev, newValue) => {\n if (!newValue) {\n setValue(null)\n } else if (Array.isArray(newValue)) {\n setValue(newValue[0] || null)\n } else {\n setValue(newValue)\n }\n }}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n variant={variant}\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n )\n}"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"name": "Variants",
|
|
80
|
+
"id": "components-autocomplete-autocomplete--variants",
|
|
81
|
+
"code": "import { Autocomplete, AutocompleteProps } from '@carto/meridian-ds/components'\n\nconst top100Films = getTop100Films()\n\nconst Variants = ({\n label,\n placeholder,\n helperText,\n error,\n size,\n required,\n disableCloseOnSelect,\n ...props\n}: AutocompleteProps<(typeof top100Films)[number]> &\n AutocompleteInputProps) => {\n return (\n <Grid container direction='column' spacing={6}>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Filled'}</Label>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n variant='filled'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Container>\n </Grid>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Outlined'}</Label>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n variant='outlined'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Container>\n </Grid>\n </Grid>\n )\n}"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"name": "LabelAndHelperText",
|
|
85
|
+
"id": "components-autocomplete-autocomplete--label-and-helper-text",
|
|
86
|
+
"code": "import { Autocomplete, AutocompleteProps } from '@carto/meridian-ds/components'\n\nconst top100Films = getTop100Films()\n\nconst LabelAndHelperText = ({\n label,\n variant,\n placeholder,\n error,\n size,\n required,\n helperText,\n disableCloseOnSelect,\n ...props\n}: AutocompleteProps<(typeof top100Films)[number]> &\n AutocompleteInputProps) => {\n return (\n <Grid container direction='column' spacing={6}>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Label + helper text'}</Label>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n variant={variant}\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Container>\n </Grid>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Without label + helper text'}</Label>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n placeholder={placeholder}\n variant={variant}\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Container>\n </Grid>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Only label'}</Label>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant={variant}\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Container>\n </Grid>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Only helper text'}</Label>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n placeholder={placeholder}\n helperText={helperText}\n variant={variant}\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Container>\n </Grid>\n </Grid>\n )\n}"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"name": "Prefix",
|
|
90
|
+
"id": "components-autocomplete-autocomplete--prefix",
|
|
91
|
+
"code": "import { Autocomplete, AutocompleteProps } from '@carto/meridian-ds/components'\n\nconst top100Films = getTop100Films()\n\nconst Prefix = ({\n label,\n variant,\n placeholder,\n helperText,\n error,\n size,\n required,\n disableCloseOnSelect,\n ...props\n}: AutocompleteProps<(typeof top100Films)[number]> &\n AutocompleteInputProps) => {\n return (\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => {\n params.InputProps.startAdornment = (\n <InputAdornment position='start'>\n {<AnalyticsOutlined />}\n </InputAdornment>\n )\n return (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n variant={variant}\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )\n }}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n )\n}"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"name": "Medium",
|
|
95
|
+
"id": "components-autocomplete-autocomplete--medium",
|
|
96
|
+
"code": "import { Autocomplete, AutocompleteProps, Typography } from '@carto/meridian-ds/components'\n\nconst top100Films = getTop100Films()\n\nconst Medium = ({\n label,\n placeholder,\n error,\n size,\n required,\n helperText,\n disableCloseOnSelect,\n ...props\n}: AutocompleteProps<(typeof top100Films)[number]> &\n AutocompleteInputProps) => {\n return (\n <Grid container spacing={6}>\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Placeholder</Typography>\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='filled'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='outlined'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Empty</Typography>\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n variant='filled'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n variant='outlined'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Filled</Typography>\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n defaultValue={top100Films[6]}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='filled'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n defaultValue={top100Films[6]}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='outlined'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Focused</Typography>\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='filled'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n focused\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='outlined'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n focused\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Disabled</Typography>\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n defaultValue={top100Films[6]}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='filled'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disabled\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='outlined'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disabled\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Read Only</Typography>\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n defaultValue={top100Films[6]}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='filled'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n InputProps={{ readOnly: true }}\n />\n )}\n size={size}\n readOnly\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n defaultValue={top100Films[6]}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='outlined'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n InputProps={{ readOnly: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Error</Typography>\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n variant='filled'\n error\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n variant='outlined'\n error\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Loading</Typography>\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='filled'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n loading\n />\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='outlined'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n loading\n />\n </Grid>\n </Grid>\n </Grid>\n )\n}"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"name": "Small",
|
|
100
|
+
"id": "components-autocomplete-autocomplete--small",
|
|
101
|
+
"code": "import { Autocomplete, AutocompleteProps, Typography } from '@carto/meridian-ds/components'\n\nconst top100Films = getTop100Films()\n\nconst Small = ({\n label,\n placeholder,\n error,\n size,\n required,\n helperText,\n disableCloseOnSelect,\n ...props\n}: AutocompleteProps<(typeof top100Films)[number]> &\n AutocompleteInputProps) => {\n return (\n <Grid container spacing={6}>\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Placeholder</Typography>\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='filled'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='outlined'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Empty</Typography>\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n variant='filled'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n variant='outlined'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Filled</Typography>\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n defaultValue={top100Films[6]}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='filled'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n defaultValue={top100Films[6]}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='outlined'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Focused</Typography>\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='filled'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n focused\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='outlined'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n focused\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Disabled</Typography>\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n defaultValue={top100Films[6]}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='filled'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disabled\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='outlined'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disabled\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Read Only</Typography>\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n defaultValue={top100Films[6]}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='filled'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n InputProps={{ readOnly: true }}\n />\n )}\n size={size}\n readOnly\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n defaultValue={top100Films[6]}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='outlined'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n InputProps={{ readOnly: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Error</Typography>\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n variant='filled'\n error\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n variant='outlined'\n error\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Loading</Typography>\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='filled'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n loading\n />\n </Grid>\n <Grid item xs>\n <Autocomplete\n {...props}\n options={top100Films}\n getOptionLabel={(option) => option.title}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n variant='outlined'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n loading\n />\n </Grid>\n </Grid>\n </Grid>\n )\n}"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"name": "CustomRenderOption",
|
|
105
|
+
"id": "components-autocomplete-autocomplete--custom-render-option",
|
|
106
|
+
"code": "import { Autocomplete, AutocompleteProps, MenuItem } from '@carto/meridian-ds/components'\nimport { useState } from 'react'\n\nconst top100FilmsStartAndEndAdornment = getTop100Films({\n includeStartAdornment: true,\n includeEndAdornment: true,\n})\n\nconst CustomRenderOption = ({\n label,\n variant,\n placeholder,\n helperText,\n error,\n size,\n required,\n disableCloseOnSelect,\n ...props\n}: AutocompleteProps<(typeof top100FilmsStartAndEndAdornment)[number]> &\n AutocompleteInputProps) => {\n const [selectedOption, setSelectedOption] = useState<\n (typeof top100FilmsStartAndEndAdornment)[number] | null\n >(null)\n\n return (\n <>\n <DocContainer severity='info'>\n Uses `startAdornment` for the icon in the input and `renderOption` to\n override default list items\n </DocContainer>\n\n <Autocomplete\n {...props}\n size={size}\n value={selectedOption}\n options={top100FilmsStartAndEndAdornment}\n getOptionLabel={(option) => `${option.title} (${option.year})`}\n onChange={(event, newValue) => {\n setSelectedOption(newValue)\n }}\n renderInput={(params) => {\n if (selectedOption) {\n params.InputProps.startAdornment = (\n <InputAdornment position='start'>\n {selectedOption.startAdornment}\n </InputAdornment>\n )\n }\n return (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n variant={variant}\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )\n }}\n renderOption={(props, option) => (\n <MenuItem {...props} key={option.title}>\n <ListItemIcon>{option.startAdornment}</ListItemIcon>\n <ListItemText>\n {option.year ? `${option.title} (${option.year})` : option.title}\n </ListItemText>\n {option.endAdornment}\n </MenuItem>\n )}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </>\n )\n}"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"name": "FreeSolo",
|
|
110
|
+
"id": "components-autocomplete-autocomplete--free-solo",
|
|
111
|
+
"code": "import { Autocomplete, AutocompleteProps } from '@carto/meridian-ds/components'\nimport { useState } from 'react'\n\nconst top100Films = getTop100Films()\n\nconst FreeSolo = ({\n label,\n variant,\n placeholder,\n helperText,\n error,\n size,\n required,\n disableCloseOnSelect,\n ...props\n}: AutocompleteProps<(typeof top100Films)[number], boolean, false, true> &\n AutocompleteInputProps) => {\n const [values, setValues] = useState<typeof top100Films>([])\n\n return (\n <>\n <DocContainer severity='info'>\n The textbox can contain any arbitrary value.\n </DocContainer>\n\n <Autocomplete\n {...props}\n freeSolo\n options={values}\n onChange={(ev, values) => {\n const newValues = Array.isArray(values) ? values : [values]\n setValues(newValues as unknown as typeof top100Films)\n }}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n variant={variant}\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </>\n )\n}"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"name": "VirtualizedList",
|
|
115
|
+
"id": "components-autocomplete-autocomplete--virtualized-list",
|
|
116
|
+
"code": "import { Autocomplete, AutocompleteList, AutocompleteListProps, AutocompleteProps, Typography, createAutocompleteGroupByList, isAutocompleteListGroupHeader, useAutocomplete } from '@carto/meridian-ds/components'\nimport { useState } from 'react'\n\nconst largeMenuList = getLargeMenuList()\n\nconst VirtualizedList = ({\n label,\n variant,\n placeholder,\n helperText,\n error,\n size,\n required,\n disableCloseOnSelect,\n ...props\n}: AutocompleteProps<(typeof largeMenuList)[number], boolean> &\n AutocompleteInputProps) => {\n const [value, setValue] = useState<StorybookFilmProps | null>(null)\n\n // Create grouped options for the grouped items example\n const sampleData = largeMenuList.map((item) => ({\n ...item,\n category: `Category ${Math.floor(Math.random() * 2000) + 1}`,\n }))\n\n const groupedOptions = createAutocompleteGroupByList({\n options: sampleData,\n groupBy: (option: (typeof sampleData)[number]) => option.category,\n })\n\n const { singleRenderOption, getOptionLabel } = useAutocomplete({\n getOptionLabel: (option) => (option as StorybookFilmProps).title,\n })\n\n return (\n <Grid container direction='column' spacing={6}>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Default'}</Label>\n <Autocomplete\n {...props}\n value={value}\n onChange={(ev, newValue) => {\n if (!newValue) {\n setValue(null)\n } else if (Array.isArray(newValue)) {\n setValue(newValue[0] || null)\n } else {\n setValue(newValue)\n }\n }}\n options={largeMenuList}\n getOptionLabel={(option) => option.title}\n ListboxComponent={AutocompleteList}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n variant={variant}\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Container>\n </Grid>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Custom ListboxProps'}</Label>\n <Autocomplete\n {...props}\n value={value}\n onChange={(ev, newValue) => {\n if (!newValue) {\n setValue(null)\n } else if (Array.isArray(newValue)) {\n setValue(newValue[0] || null)\n } else {\n setValue(newValue)\n }\n }}\n options={largeMenuList}\n getOptionLabel={(option) => option.title}\n ListboxComponent={AutocompleteList}\n ListboxProps={\n {\n itemHeight: 24,\n maxListHeight: 200,\n } as AutocompleteListProps\n }\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n variant={variant}\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Container>\n </Grid>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Grouped items'}</Label>\n <Autocomplete\n {...props}\n value={value}\n onChange={(ev, newValue) => {\n if (!newValue) {\n setValue(null)\n } else if (Array.isArray(newValue)) {\n const firstValue: unknown = newValue[0]\n // Filter out group headers and arrays\n if (\n firstValue &&\n typeof firstValue === 'object' &&\n 'title' in firstValue &&\n !isAutocompleteListGroupHeader(firstValue)\n ) {\n setValue(firstValue as StorybookFilmProps)\n } else {\n setValue(null)\n }\n } else {\n // Filter out group headers\n if (\n typeof newValue === 'object' &&\n 'title' in newValue &&\n !isAutocompleteListGroupHeader(newValue)\n ) {\n setValue(newValue as StorybookFilmProps)\n } else {\n setValue(null)\n }\n }\n }}\n options={groupedOptions}\n getOptionLabel={getOptionLabel}\n renderOption={singleRenderOption}\n ListboxComponent={AutocompleteList}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n variant={variant}\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Container>\n </Grid>\n <Grid item>\n <DocContainer severity='info'>\n <Typography variant='body2' mb={2}>\n Regular Autocomplete doesn't support virtualization by default\n to prioritize flexibility. If you need virtualization, use the\n `AutocompleteList` component, which is a wrapper around\n `react-window` and is optimized for virtualization.\n </Typography>\n <Typography variant='body2' weight='strong' mb={2}>\n Virtualization Examples\n </Typography>\n <Typography variant='body2' weight='strong' mb={2}>\n 1. Basic Virtualization:\n </Typography>\n <Typography variant='body2' component='div' mb={2}>\n {`<Autocomplete ListboxComponent={AutocompleteList} />`}\n </Typography>\n <Typography variant='body2' weight='strong' mb={2}>\n 2. Custom Height Settings:\n </Typography>\n <Typography variant='body2' component='div' mb={2}>\n {`ListboxProps={{ itemHeight: 24, maxListHeight: 200 }}`}\n </Typography>\n <Typography variant='body2' weight='strong' mb={2}>\n 3. Grouped Virtualization:\n </Typography>\n <Typography variant='body2' component='div' mb={1}>\n {`const groupedOptions = createAutocompleteGroupByList(data, (item) => item.category)`}\n </Typography>\n <Typography variant='body2' component='div' mb={1}>\n {` const { singleRenderOption, getOptionLabel } = useAutocomplete({\n getOptionLabel: (option) => option.title,\n })`}\n </Typography>\n <Typography variant='body2' component='div' mb={2}>\n {`<Autocomplete options={groupedOptions} renderOption={singleRenderOption} getOptionLabel={getOptionLabel} />`}\n </Typography>\n <Typography variant='body2'>\n Group headers are automatically styled as subtitles with proper\n dividers and cannot be selected.\n </Typography>\n </DocContainer>\n </Grid>\n </Grid>\n )\n}"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"name": "GroupedVirtualization",
|
|
120
|
+
"id": "components-autocomplete-autocomplete--grouped-virtualization",
|
|
121
|
+
"code": "import { Autocomplete, AutocompleteList, AutocompleteListProps, AutocompleteProps, Typography, createAutocompleteGroupByList, isAutocompleteListGroupHeader, useAutocomplete } from '@carto/meridian-ds/components'\nimport { useState } from 'react'\n\nconst GroupedVirtualization = ({\n label,\n placeholder,\n error,\n size,\n required,\n helperText,\n disableCloseOnSelect,\n ...props\n}: AutocompleteProps<unknown, boolean> & AutocompleteInputProps) => {\n const [value, setValue] = useState<{\n category: string\n title: string\n } | null>(null)\n const [valueExtended, setValueExtended] = useState<{\n category: string\n title: string\n secondaryText: string\n extended: boolean\n } | null>(null)\n\n const sampleData = Array.from({ length: 10000 }, (_, index) => ({\n title: `Movie ${index + 1}`,\n category: `Category ${Math.floor(Math.random() * 2000) + 1}`,\n }))\n\n const sampleDataExtended = Array.from({ length: 10000 }, (_, index) => ({\n title: `Movie ${index + 1}`,\n secondaryText: `Subtitle ${index + 1}`,\n extended: true,\n category: `Category ${Math.floor(Math.random() * 2000) + 1}`,\n }))\n\n type DataWithCategory = (typeof sampleData)[number]\n type DataWithCategoryExtended = (typeof sampleDataExtended)[number]\n\n // Create the grouped options list\n const groupedOptions = createAutocompleteGroupByList({\n options: sampleData,\n groupBy: (option: DataWithCategory) => option.category,\n })\n\n const groupedOptionsExtended = createAutocompleteGroupByList({\n options: sampleDataExtended,\n groupBy: (option: DataWithCategoryExtended) => option.category,\n extended: true,\n })\n\n const { singleRenderOption, getOptionLabel } = useAutocomplete({\n getOptionLabel: (option) => (option as DataWithCategory).title,\n })\n\n const {\n singleRenderOption: singleRenderOptionExtended,\n getOptionLabel: getOptionLabelExtended,\n } = useAutocomplete({\n getOptionLabel: (option) => (option as DataWithCategoryExtended).title,\n })\n\n return (\n <Grid container direction='column' spacing={6}>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Grouped (default)'}</Label>\n <Autocomplete\n {...props}\n value={value}\n onChange={(ev, newValue) => {\n if (!newValue) {\n setValue(null)\n } else if (Array.isArray(newValue)) {\n const firstValue: unknown = newValue[0]\n // Filter out group headers\n if (\n firstValue &&\n typeof firstValue === 'object' &&\n 'title' in firstValue &&\n !isAutocompleteListGroupHeader(firstValue)\n ) {\n setValue(firstValue as DataWithCategory)\n } else {\n setValue(null)\n }\n } else {\n // Filter out group headers\n if (\n typeof newValue === 'object' &&\n 'title' in newValue &&\n !isAutocompleteListGroupHeader(newValue)\n ) {\n setValue(newValue as DataWithCategory)\n } else {\n setValue(null)\n }\n }\n }}\n options={groupedOptions as unknown[]}\n getOptionLabel={getOptionLabel}\n isOptionEqualToValue={(option, value) => {\n // Skip group headers\n if (\n isAutocompleteListGroupHeader(option) ||\n isAutocompleteListGroupHeader(value)\n ) {\n return false\n }\n return (\n (option as DataWithCategory).title ===\n (value as DataWithCategory).title\n )\n }}\n renderOption={singleRenderOption}\n ListboxComponent={AutocompleteList}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n variant='outlined'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Container>\n </Grid>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Grouped (extended)'}</Label>\n <Autocomplete\n {...props}\n value={valueExtended}\n onChange={(ev, newValue) => {\n if (!newValue) {\n setValueExtended(null)\n } else if (Array.isArray(newValue)) {\n const firstValue: unknown = newValue[0]\n // Filter out group headers\n if (\n firstValue &&\n typeof firstValue === 'object' &&\n 'title' in firstValue &&\n !isAutocompleteListGroupHeader(firstValue)\n ) {\n setValueExtended(firstValue as DataWithCategoryExtended)\n } else {\n setValueExtended(null)\n }\n } else {\n // Filter out group headers\n if (\n typeof newValue === 'object' &&\n 'title' in newValue &&\n !isAutocompleteListGroupHeader(newValue)\n ) {\n setValueExtended(newValue as DataWithCategoryExtended)\n } else {\n setValueExtended(null)\n }\n }\n }}\n options={groupedOptionsExtended as unknown[]}\n getOptionLabel={getOptionLabelExtended}\n isOptionEqualToValue={(option, value) => {\n // Skip group headers\n if (\n isAutocompleteListGroupHeader(option) ||\n isAutocompleteListGroupHeader(value)\n ) {\n return false\n }\n return (\n (option as DataWithCategoryExtended).title ===\n (value as DataWithCategoryExtended).title\n )\n }}\n renderOption={singleRenderOptionExtended}\n ListboxComponent={AutocompleteList}\n ListboxProps={\n {\n extended: true,\n } as AutocompleteListProps\n }\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n variant='outlined'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Container>\n </Grid>\n <Grid item>\n <DocContainer severity='info'>\n <Typography variant='body2' weight='strong' mb={2}>\n Grouped Options Usage\n </Typography>\n <Typography variant='body2' mb={2}>\n To create grouped options that work with virtualization:\n </Typography>\n <Typography variant='body2' component='div' mb={1}>\n <DocHighlight component='span'>\n {`const groupedOptions = createAutocompleteGroupByList(data, (item) => item.category)`}\n </DocHighlight>\n </Typography>\n <Typography variant='body2' component='div' mb={1}>\n <DocHighlight component='span'>\n {`const { singleRenderOption, getOptionLabel } = useAutocomplete({ getOptionLabel: (option) => option.title })`}\n </DocHighlight>\n </Typography>\n <Typography variant='body2' component='div' mb={2}>\n <DocHighlight component='span'>\n {`<Autocomplete options={groupedOptions} ListboxComponent={AutocompleteList} renderOption={singleRenderOption} getOptionLabel={getOptionLabel} />`}\n </DocHighlight>\n </Typography>\n <Typography variant='body2' mb={2}>\n <strong>Note:</strong> The native MUI `groupBy` prop is not\n supported as it breaks virtualization. Use\n `createAutocompleteGroupByList` instead to maintain efficient\n rendering.\n </Typography>\n <Typography variant='body2' weight='strong' mb={1}>\n Key Benefits:\n </Typography>\n <Typography variant='body2' component='div' mb={1}>\n • Maintains virtualization performance with large datasets\n </Typography>\n <Typography variant='body2' component='div' mb={1}>\n • Automatic group header styling and dividers\n </Typography>\n <Typography variant='body2' component='div' mb={1}>\n • Works with all autocomplete variants (single, multiple, etc.)\n </Typography>\n <Typography variant='body2' component='div' mb={1}>\n • Supports both default and extended group header styles\n </Typography>\n </DocContainer>\n </Grid>\n </Grid>\n )\n}"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"name": "GroupedNonVirtualized",
|
|
125
|
+
"id": "components-autocomplete-autocomplete--grouped-non-virtualized",
|
|
126
|
+
"code": "import { Autocomplete, AutocompleteProps, MenuItem, Typography, useAutocomplete } from '@carto/meridian-ds/components'\nimport React, { useState } from 'react'\n\nconst top100Films = getTop100Films()\n\nconst GroupedNonVirtualized = ({\n label,\n placeholder,\n error,\n size,\n required,\n helperText,\n disableCloseOnSelect,\n}: AutocompleteProps<FilmWithCategory, boolean> & AutocompleteInputProps) => {\n const [value, setValue] = useState<FilmWithCategory | null>(null)\n const [valueExtended, setValueExtended] =\n useState<FilmWithCategoryExtended | null>(null)\n\n // Smaller dataset suitable for non-virtualized rendering\n // Note: MUI's groupBy only groups consecutive items, it doesn't sort them.\n // We must sort by category to avoid repeated group headers.\n const filmsWithCategory: FilmWithCategory[] = top100Films\n .map((film) => ({\n ...film,\n category: (film.year ?? 0) < 1970 ? 'Classic' : 'Contemporary',\n }))\n .sort((a, b) => a.category.localeCompare(b.category))\n\n const filmsWithCategoryExtended: FilmWithCategoryExtended[] = top100Films\n .map((film) => ({\n ...film,\n secondaryText: `Released in ${film.year ?? 'Unknown'}`,\n extended: true,\n category: (film.year ?? 0) < 1970 ? 'Classic' : 'Contemporary',\n }))\n .sort((a, b) => a.category.localeCompare(b.category))\n\n const { singleRenderOption } = useAutocomplete({\n getOptionLabel: (option) => (option as FilmWithCategoryExtended).title,\n })\n\n return (\n <Grid container direction='column' spacing={6}>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Native groupBy (non-virtualized)'}</Label>\n <Autocomplete<FilmWithCategory, false>\n value={value}\n onChange={(_, newValue) => {\n setValue(newValue)\n }}\n options={filmsWithCategory}\n getOptionLabel={(option) => option.title}\n isOptionEqualToValue={(option, value) =>\n option.title === value.title\n }\n groupBy={(option) => option.category}\n renderGroup={(params) => (\n <React.Fragment key={params.key}>\n <MenuItem subtitle>{params.group}</MenuItem>\n {params.children}\n </React.Fragment>\n )}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n variant='outlined'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Container>\n </Grid>\n <Grid item>\n <Container>\n <Label variant='body2'>\n {'Native groupBy (non-virtualized, extended)'}\n </Label>\n <Autocomplete<FilmWithCategoryExtended, false>\n value={valueExtended}\n onChange={(_, newValue) => {\n setValueExtended(newValue)\n }}\n options={filmsWithCategoryExtended}\n getOptionLabel={(option) => option.title}\n isOptionEqualToValue={(option, value) =>\n option.title === value.title\n }\n groupBy={(option) => option.category}\n renderGroup={(params) => (\n <React.Fragment key={params.key}>\n <MenuItem subtitle>{params.group}</MenuItem>\n {params.children}\n </React.Fragment>\n )}\n renderOption={singleRenderOption}\n renderInput={(params) => (\n <TextField\n {...params}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n variant='outlined'\n error={error}\n size={size}\n required={required}\n InputLabelProps={{ shrink: true }}\n />\n )}\n size={size}\n disableCloseOnSelect={disableCloseOnSelect}\n />\n </Container>\n </Grid>\n <Grid item>\n <DocContainer severity='info'>\n <Typography variant='body2' weight='strong' mb={2}>\n Non-Virtualized Grouped Autocomplete\n </Typography>\n <Typography variant='body2' mb={2}>\n This example uses MUI's native `groupBy` prop, which is ideal\n for smaller datasets where virtualization is not needed.\n </Typography>\n <Typography variant='body2' component='div' mb={2}>\n <DocHighlight component='span'>\n {`<Autocomplete\n options={options}\n groupBy={(option) => option.category}\n renderGroup={(params) => (\n <li key={params.key}>\n <MenuItem subtitle>{params.group}</MenuItem>\n <ul style={{ padding: 0 }}>{params.children}</ul>\n </li>\n )}\n/>`}\n </DocHighlight>\n </Typography>\n <Typography variant='body2' weight='strong' mb={1}>\n When to use:\n </Typography>\n <Typography variant='body2' component='div' mb={1}>\n • Small to medium datasets (under 100-200 items)\n </Typography>\n <Typography variant='body2' component='div' mb={1}>\n • When virtualization is not required\n </Typography>\n <Typography variant='body2' component='div' mb={1}>\n • Simple grouping needs without custom styling\n </Typography>\n <Typography variant='body2' mt={2}>\n <strong>Note:</strong> For large datasets, use the virtualized\n `GroupedVirtualization` story which uses\n `createAutocompleteGroupByList` to maintain performance.\n </Typography>\n </DocContainer>\n </Grid>\n </Grid>\n )\n}"
|
|
127
|
+
}
|
|
128
|
+
]
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"name": "Button",
|
|
132
|
+
"description": "Standard action button for user-triggered actions. Supports loading state and rendering as an external link.",
|
|
133
|
+
"curation": {
|
|
134
|
+
"keywords": [
|
|
135
|
+
"submit",
|
|
136
|
+
"cta",
|
|
137
|
+
"call to action",
|
|
138
|
+
"primary action",
|
|
139
|
+
"click"
|
|
140
|
+
],
|
|
141
|
+
"mui": [
|
|
142
|
+
"color",
|
|
143
|
+
{
|
|
144
|
+
"name": "variant",
|
|
145
|
+
"aiHint": "Use 'contained' for primary actions, 'outlined' for secondary actions, 'text' for tertiary actions. Don't use multiple contained buttons in the same row"
|
|
146
|
+
},
|
|
147
|
+
"size",
|
|
148
|
+
"startIcon",
|
|
149
|
+
"endIcon",
|
|
150
|
+
"fullWidth",
|
|
151
|
+
{
|
|
152
|
+
"name": "disabled",
|
|
153
|
+
"aiHint": "Pair with a Tooltip explaining why the action is unavailable - a silently disabled button looks broken to users."
|
|
154
|
+
},
|
|
155
|
+
"href"
|
|
156
|
+
],
|
|
157
|
+
"decisionTree": [
|
|
158
|
+
{
|
|
159
|
+
"condition": "Navigation to a URL",
|
|
160
|
+
"use": "Link",
|
|
161
|
+
"aiHint": "Use Link for href-based navigation, not onClick actions"
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"condition": "Icon-only action",
|
|
165
|
+
"use": "IconButton",
|
|
166
|
+
"aiHint": "No text label needed; always pair with a tooltip"
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
"condition": "Toggle state (on/off, active/inactive)",
|
|
170
|
+
"use": "ToggleButton",
|
|
171
|
+
"isMUI": true
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"condition": "Dropdown action has multiple variants or no clear default",
|
|
175
|
+
"use": "SplitButton"
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"condition": "Copying text to clipboard",
|
|
179
|
+
"use": "CopiableComponent",
|
|
180
|
+
"aiHint": "Adds copy-to-clipboard with tooltip and success notification"
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"condition": "Selecting a filter value triggered by a button or icon",
|
|
184
|
+
"use": "FilterDropdown",
|
|
185
|
+
"aiHint": "Triggered by a button/icon, single option selection"
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"condition": "Selecting a sort or setting value in a form",
|
|
189
|
+
"use": "SelectField",
|
|
190
|
+
"aiHint": "Not an action trigger, just selecting a value"
|
|
191
|
+
}
|
|
192
|
+
]
|
|
193
|
+
},
|
|
194
|
+
"examples": [
|
|
195
|
+
{
|
|
196
|
+
"name": "Playground",
|
|
197
|
+
"id": "components-buttons-button--playground",
|
|
198
|
+
"code": "import { Button, ButtonProps } from '@carto/meridian-ds/components'\n\nconst Playground = (args: ButtonProps) => <Button {...args} />"
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"name": "Variants",
|
|
202
|
+
"id": "components-buttons-button--variants",
|
|
203
|
+
"code": "import { Button, ButtonProps, Typography } from '@carto/meridian-ds/components'\n\nconst VariantTemplate = ({ children, ...rest }: ButtonProps) => {\n const smallLabel = children ? children : 'Small button'\n const mediumLabel = children ? children : 'Medium button'\n const largeLabel = children ? children : 'Large button'\n const disabledLabel = children ? children : 'Disabled button'\n\n return (\n <Grid container spacing={2}>\n <Grid item container spacing={2}>\n <Grid item xs={4}>\n <Button {...rest} size='small'>\n {smallLabel}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button {...rest} size='small' startIcon={<Add />}>\n {smallLabel}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button {...rest} size='small' endIcon={<Close />}>\n {smallLabel}\n </Button>\n </Grid>\n </Grid>\n <Grid item container spacing={2}>\n <Grid item xs={4}>\n <Button {...rest} size='medium'>\n {mediumLabel}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button {...rest} size='medium' startIcon={<Add />}>\n {mediumLabel}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button {...rest} size='medium' endIcon={<Close />}>\n {mediumLabel}\n </Button>\n </Grid>\n </Grid>\n <Grid item container spacing={2}>\n <Grid item xs={4}>\n <Button {...rest} size='large'>\n {largeLabel}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button {...rest} size='large' startIcon={<Add />}>\n {largeLabel}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button {...rest} size='large' endIcon={<Close />}>\n {largeLabel}\n </Button>\n </Grid>\n </Grid>\n <Grid item container spacing={2}>\n <Grid item xs={4}>\n <Button {...rest} disabled>\n {disabledLabel}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button {...rest} disabled startIcon={<Add />}>\n {disabledLabel}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button {...rest} disabled endIcon={<Close />}>\n {disabledLabel}\n </Button>\n </Grid>\n </Grid>\n </Grid>\n )\n}\n\nconst Variants = (props: ButtonProps) => (\n <Grid container direction='column' spacing={4}>\n {variantsButton.map((variant) => (\n <Grid item key={variant}>\n <Typography variant='subtitle2' sx={{ mb: 1 }}>\n {variant}\n </Typography>\n <VariantTemplate\n {...props}\n variant={variant as ButtonProps['variant']}\n />\n </Grid>\n ))}\n </Grid>\n)"
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"name": "Colors",
|
|
207
|
+
"id": "components-buttons-button--colors",
|
|
208
|
+
"code": "import { Button, ButtonProps, Typography } from '@carto/meridian-ds/components'\n\nconst ColorTemplate = ({ children, ...rest }: ButtonProps) => {\n const containedLabel = children ? children : 'Contained button'\n const outlinedLabel = children ? children : 'Outlined button'\n const textLabel = children ? children : 'Text button'\n\n return (\n <Grid container spacing={2}>\n <Grid item container spacing={2}>\n <Grid item xs={4}>\n <Button {...rest} variant='contained'>\n {containedLabel}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button {...rest} variant='contained' startIcon={<Add />}>\n {containedLabel}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button {...rest} variant='contained' endIcon={<Close />}>\n {containedLabel}\n </Button>\n </Grid>\n </Grid>\n <Grid item container spacing={2}>\n <Grid item xs={4}>\n <Button {...rest} variant='outlined'>\n {outlinedLabel}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button {...rest} variant='outlined' startIcon={<Add />}>\n {outlinedLabel}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button {...rest} variant='outlined' endIcon={<Close />}>\n {outlinedLabel}\n </Button>\n </Grid>\n </Grid>\n <Grid item container spacing={2}>\n <Grid item xs={4}>\n <Button {...rest} variant='text'>\n {textLabel}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button {...rest} variant='text' startIcon={<Add />}>\n {textLabel}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button {...rest} variant='text' endIcon={<Close />}>\n {textLabel}\n </Button>\n </Grid>\n </Grid>\n </Grid>\n )\n}\n\nconst Colors = (props: ButtonProps) => (\n <Grid container direction='column' spacing={4}>\n {colorsButton.map((color) => (\n <Grid item key={color}>\n <Typography variant='subtitle2' sx={{ mb: 1 }}>\n {color}\n </Typography>\n <ColorTemplate {...props} color={color as ButtonProps['color']} />\n </Grid>\n ))}\n </Grid>\n)"
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
"name": "Behavior",
|
|
212
|
+
"id": "components-buttons-button--behavior",
|
|
213
|
+
"code": "import { Button, ButtonProps, Typography } from '@carto/meridian-ds/components'\n\nconst Behavior = ({ children, ...rest }: ButtonProps) => {\n const overflowLabel = 'Text Button with overflow'\n\n return (\n <Grid container direction='column' spacing={6}>\n <Grid item container direction='column' xs={4}>\n <Typography variant='body1' sx={{ mb: 2 }}>\n {'Overflow + tooltip'}\n </Typography>\n <Grid container spacing={2}>\n <Grid item xs={4}>\n <Tooltip title={overflowLabel}>\n <Button {...rest}>{overflowLabel}</Button>\n </Tooltip>\n </Grid>\n <Grid item xs={4}>\n <Tooltip title={overflowLabel}>\n <Button {...rest} startIcon={<Add />}>\n {overflowLabel}\n </Button>\n </Tooltip>\n </Grid>\n <Grid item xs={4}>\n <Tooltip title={overflowLabel}>\n <Button {...rest} endIcon={<Close />}>\n {overflowLabel}\n </Button>\n </Tooltip>\n </Grid>\n </Grid>\n </Grid>\n\n <Grid item container direction='column' xs={4}>\n <Typography variant='body1' sx={{ mb: 2 }}>\n {'Pairing buttons'}\n </Typography>\n <Grid container spacing={2}>\n <Grid item>\n <Button {...rest}>{children}</Button>\n <Button {...rest} startIcon={<Add />}>\n {children}\n </Button>\n </Grid>\n </Grid>\n </Grid>\n\n <Grid item container direction='column' xs={4}>\n <Typography variant='body1' sx={{ mb: 2 }}>\n {'Loading'}\n </Typography>\n <Grid container spacing={2}>\n <Grid item xs={4}>\n <Button loading variant='contained'>\n {children}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button\n loading\n loadingPosition='start'\n variant='contained'\n startIcon={<Add />}\n >\n {children}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button\n loading\n loadingPosition='end'\n variant='contained'\n endIcon={<Close />}\n >\n {children}\n </Button>\n </Grid>\n </Grid>\n </Grid>\n </Grid>\n )\n}"
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
"name": "ExternalLink",
|
|
217
|
+
"id": "components-buttons-button--external-link",
|
|
218
|
+
"code": "import { Button, ButtonProps, Typography } from '@carto/meridian-ds/components'\n\nconst ExternalLink = ({ children, ...rest }: ButtonProps) => {\n return (\n <Grid container direction='column' spacing={4}>\n <Grid item container direction='column'>\n <Typography variant='body1' sx={{ mb: 2 }}>\n {'External Link Buttons (with href)'}\n </Typography>\n <Grid container spacing={2}>\n <Grid item xs={4}>\n <Button {...rest} variant='contained'>\n {children}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button {...rest} variant='outlined'>\n {children}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button {...rest} variant='text'>\n {children}\n </Button>\n </Grid>\n </Grid>\n </Grid>\n\n <Grid item container direction='column'>\n <Typography variant='body1' sx={{ mb: 2 }}>\n {'External with Custom End Icon (custom icon takes precedence)'}\n </Typography>\n <Grid container spacing={2}>\n <Grid item xs={4}>\n <Button {...rest} endIcon={<Close />} variant='contained'>\n {children}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button {...rest} endIcon={<Close />} variant='outlined'>\n {children}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button {...rest} endIcon={<Close />} variant='text'>\n {children}\n </Button>\n </Grid>\n </Grid>\n </Grid>\n\n <Grid item container direction='column'>\n <Typography variant='body1' sx={{ mb: 2 }}>\n {'External without End Icon'}\n </Typography>\n <Grid container spacing={2}>\n <Grid item xs={4}>\n <Button {...rest} showExternalIcon={false} variant='contained'>\n {children}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button {...rest} showExternalIcon={false} variant='outlined'>\n {children}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button {...rest} showExternalIcon={false} variant='text'>\n {children}\n </Button>\n </Grid>\n </Grid>\n </Grid>\n\n <Grid item container direction='column'>\n <Typography variant='body1' sx={{ mb: 2 }}>\n {\n 'External with Custom screenReaderText (custom text for screen readers)'\n }\n </Typography>\n <Grid container spacing={2}>\n <Grid item xs={4}>\n <Button\n {...rest}\n screenReaderText='Se abre en nueva pestaña'\n variant='contained'\n >\n {children}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button\n {...rest}\n screenReaderText='Se abre en nueva pestaña'\n variant='outlined'\n >\n {children}\n </Button>\n </Grid>\n <Grid item xs={4}>\n <Button\n {...rest}\n screenReaderText='Se abre en nueva pestaña'\n variant='text'\n >\n {children}\n </Button>\n </Grid>\n </Grid>\n </Grid>\n </Grid>\n )\n}"
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"name": "Dialog",
|
|
224
|
+
"description": "Modal dialog for focused tasks, confirmations, forms, and multi-step wizards (with DialogStepper). Not for full-page content — use routing instead. Composes with DialogHeader, DialogContent, and DialogFooter.",
|
|
225
|
+
"curation": {
|
|
226
|
+
"keywords": [
|
|
227
|
+
"popup",
|
|
228
|
+
"overlay"
|
|
229
|
+
],
|
|
230
|
+
"mui": [
|
|
231
|
+
"open",
|
|
232
|
+
{
|
|
233
|
+
"name": "onClose",
|
|
234
|
+
"aiHint": "Handle both backdropClick and escapeKeyDown reasons. Pass to DialogHeader's onClose for the close button."
|
|
235
|
+
},
|
|
236
|
+
"fullWidth",
|
|
237
|
+
"maxWidth",
|
|
238
|
+
{
|
|
239
|
+
"name": "fullScreen",
|
|
240
|
+
"aiHint": "Reserve for content-heavy flows (code editors, complex multi-step wizards). For simple confirmations or short forms, leave it off and let the size/width/height props shape the dialog."
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"name": "aria-label",
|
|
244
|
+
"aiHint": "Required for accessibility. Describes the dialog purpose."
|
|
245
|
+
}
|
|
246
|
+
],
|
|
247
|
+
"decisionTree": [
|
|
248
|
+
{
|
|
249
|
+
"condition": "Brief auto-dismissing notification",
|
|
250
|
+
"use": "Snackbar"
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
"condition": "Non-blocking inline message or warning",
|
|
254
|
+
"use": "Alert",
|
|
255
|
+
"isMUI": true
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
"condition": "Quick selection anchored to a trigger",
|
|
259
|
+
"use": "Menu"
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
"condition": "Non-blocking, transient notification",
|
|
263
|
+
"use": "Snackbar",
|
|
264
|
+
"aiHint": "Dialogs block the rest of the UI; use Snackbar for non-blocking confirmations and Alert for inline status."
|
|
265
|
+
}
|
|
266
|
+
]
|
|
267
|
+
},
|
|
268
|
+
"examples": [
|
|
269
|
+
{
|
|
270
|
+
"name": "Playground",
|
|
271
|
+
"id": "components-dialogs-dialog--playground",
|
|
272
|
+
"code": "import { Alert, Button, Dialog, DialogContent, DialogFooter, DialogHeader, DialogStepper, Typography } from '@carto/meridian-ds/components'\nimport { useTheme } from '@mui/material'\nimport { useState } from 'react'\n\nconst SampleContentSmall = () => (\n <>\n <Typography variant='body2' color='textSecondary'>\n Numeric, string and boolean are supported.\n </Typography>\n\n <div>\n <Alert severity='warning'>\n <Typography variant='code3' component='pre'>\n {someRandomCode}\n </Typography>\n </Alert>\n </div>\n </>\n)\n\nconst BaseDialog = ({\n title,\n chipLabel,\n scrollableContent,\n closeButton,\n children,\n showActions,\n showStepper,\n withGutter = true,\n withBottomGutter = true,\n spacing,\n nonModal = true,\n ...dialogArgs\n}: DialogStoryProps) => {\n const theme = useTheme()\n const [open, setOpen] = useState(false)\n\n const handleClickOpen = (): void => {\n setOpen(!open)\n }\n\n const handleClose = () => setOpen(false)\n\n return (\n <Box\n sx={{\n p: 2,\n backgroundColor: nonModal ? theme.palette.black[12] : 'transparent',\n }}\n >\n {!nonModal && (\n <Button variant='outlined' color='primary' onClick={handleClickOpen}>\n {open ? 'Close' : 'Open'} modal dialog\n </Button>\n )}\n <Dialog\n {...dialogArgs}\n open={open}\n onClose={closeButton ? handleClose : undefined}\n nonModal={nonModal}\n >\n <DialogHeader\n onClose={closeButton ? handleClose : undefined}\n chipLabel={chipLabel}\n title={title}\n >\n {showStepper && (\n <DialogStepper\n currentStep={1}\n stepsLabels={['Step 1', 'Step 2', 'Step 3']}\n />\n )}\n </DialogHeader>\n <DialogContent\n scrollableContent={scrollableContent}\n withGutter={withGutter}\n withBottomGutter={withBottomGutter}\n spacing={spacing}\n >\n {children}\n </DialogContent>\n {showActions && (\n <DialogFooter>\n <Button variant='contained' onClick={handleClose}>\n Done\n </Button>\n </DialogFooter>\n )}\n </Dialog>\n </Box>\n )\n}\n\nconst someRandomCode = `export default {\n title: 'Components/Dialogs/Dialog',\n component: Dialog,\n tags: ['autodocs']\n}\n`\n\nconst Playground = (args: DialogStoryProps) => {\n return (\n <BaseDialog {...args}>\n <SampleContentSmall />\n </BaseDialog>\n )\n}"
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
"name": "Types",
|
|
276
|
+
"id": "components-dialogs-dialog--types",
|
|
277
|
+
"code": "import { Alert, Button, Dialog, DialogContent, DialogFooter, DialogHeader, DialogStepper, Typography } from '@carto/meridian-ds/components'\nimport { useTheme } from '@mui/material'\nimport { useState } from 'react'\n\nconst SampleContentSmall = () => (\n <>\n <Typography variant='body2' color='textSecondary'>\n Numeric, string and boolean are supported.\n </Typography>\n\n <div>\n <Alert severity='warning'>\n <Typography variant='code3' component='pre'>\n {someRandomCode}\n </Typography>\n </Alert>\n </div>\n </>\n)\n\nconst BaseDialog = ({\n title,\n chipLabel,\n scrollableContent,\n closeButton,\n children,\n showActions,\n showStepper,\n withGutter = true,\n withBottomGutter = true,\n spacing,\n nonModal = true,\n ...dialogArgs\n}: DialogStoryProps) => {\n const theme = useTheme()\n const [open, setOpen] = useState(false)\n\n const handleClickOpen = (): void => {\n setOpen(!open)\n }\n\n const handleClose = () => setOpen(false)\n\n return (\n <Box\n sx={{\n p: 2,\n backgroundColor: nonModal ? theme.palette.black[12] : 'transparent',\n }}\n >\n {!nonModal && (\n <Button variant='outlined' color='primary' onClick={handleClickOpen}>\n {open ? 'Close' : 'Open'} modal dialog\n </Button>\n )}\n <Dialog\n {...dialogArgs}\n open={open}\n onClose={closeButton ? handleClose : undefined}\n nonModal={nonModal}\n >\n <DialogHeader\n onClose={closeButton ? handleClose : undefined}\n chipLabel={chipLabel}\n title={title}\n >\n {showStepper && (\n <DialogStepper\n currentStep={1}\n stepsLabels={['Step 1', 'Step 2', 'Step 3']}\n />\n )}\n </DialogHeader>\n <DialogContent\n scrollableContent={scrollableContent}\n withGutter={withGutter}\n withBottomGutter={withBottomGutter}\n spacing={spacing}\n >\n {children}\n </DialogContent>\n {showActions && (\n <DialogFooter>\n <Button variant='contained' onClick={handleClose}>\n Done\n </Button>\n </DialogFooter>\n )}\n </Dialog>\n </Box>\n )\n}\n\nconst someRandomCode = `export default {\n title: 'Components/Dialogs/Dialog',\n component: Dialog,\n tags: ['autodocs']\n}\n`\n\nconst Types = (args: DialogStoryProps) => {\n return (\n <>\n <Typography variant='subtitle1' color='textSecondary' mt={3} mb={1}>\n Stepper\n </Typography>\n\n <BaseDialog\n {...args}\n open={true}\n showActions={false}\n showStepper={false}\n nonModal={true}\n >\n <SampleContentSmall />\n </BaseDialog>\n\n <Typography variant='subtitle1' color='textSecondary' mt={3} mb={1}>\n Actions\n </Typography>\n <BaseDialog\n {...args}\n open={true}\n showActions={true}\n showStepper={false}\n nonModal={true}\n >\n <SampleContentSmall />\n </BaseDialog>\n\n <Typography variant='subtitle1' color='textSecondary' mt={3} mb={1}>\n Stepper and Actions\n </Typography>\n <BaseDialog\n {...args}\n open={true}\n showActions={true}\n showStepper={true}\n nonModal={true}\n >\n <SampleContentSmall />\n </BaseDialog>\n </>\n )\n}"
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"name": "GutterContent",
|
|
281
|
+
"id": "components-dialogs-dialog--gutter-content",
|
|
282
|
+
"code": "import { Button, Dialog, DialogContent, DialogFooter, DialogHeader, DialogStepper, Typography } from '@carto/meridian-ds/components'\nimport { useTheme } from '@mui/material'\nimport { useState } from 'react'\n\nconst BaseDialog = ({\n title,\n chipLabel,\n scrollableContent,\n closeButton,\n children,\n showActions,\n showStepper,\n withGutter = true,\n withBottomGutter = true,\n spacing,\n nonModal = true,\n ...dialogArgs\n}: DialogStoryProps) => {\n const theme = useTheme()\n const [open, setOpen] = useState(false)\n\n const handleClickOpen = (): void => {\n setOpen(!open)\n }\n\n const handleClose = () => setOpen(false)\n\n return (\n <Box\n sx={{\n p: 2,\n backgroundColor: nonModal ? theme.palette.black[12] : 'transparent',\n }}\n >\n {!nonModal && (\n <Button variant='outlined' color='primary' onClick={handleClickOpen}>\n {open ? 'Close' : 'Open'} modal dialog\n </Button>\n )}\n <Dialog\n {...dialogArgs}\n open={open}\n onClose={closeButton ? handleClose : undefined}\n nonModal={nonModal}\n >\n <DialogHeader\n onClose={closeButton ? handleClose : undefined}\n chipLabel={chipLabel}\n title={title}\n >\n {showStepper && (\n <DialogStepper\n currentStep={1}\n stepsLabels={['Step 1', 'Step 2', 'Step 3']}\n />\n )}\n </DialogHeader>\n <DialogContent\n scrollableContent={scrollableContent}\n withGutter={withGutter}\n withBottomGutter={withBottomGutter}\n spacing={spacing}\n >\n {children}\n </DialogContent>\n {showActions && (\n <DialogFooter>\n <Button variant='contained' onClick={handleClose}>\n Done\n </Button>\n </DialogFooter>\n )}\n </Dialog>\n </Box>\n )\n}\n\nconst GutterContent = (args: DialogStoryProps) => {\n return (\n <>\n <Typography variant='subtitle1' color='textSecondary' mb={1}>\n {'WithGutter (default)'}\n </Typography>\n <BaseDialog\n {...args}\n open={true}\n nonModal={true}\n showActions={true}\n title={args.title}\n >\n <img src={Map} alt='Map sample' />\n </BaseDialog>\n\n <Typography variant='subtitle1' color='textSecondary' mt={3} mb={1}>\n {'Without gutter (withGutter={false})'}\n </Typography>\n <BaseDialog\n {...args}\n open={true}\n nonModal={true}\n showActions={true}\n withGutter={false}\n title={args.title}\n >\n <img src={Map} alt='Map sample' />\n </BaseDialog>\n\n <Typography variant='subtitle1' color='textSecondary' mt={3} mb={1}>\n {'Without bottom gutter (withBottomGutter={false})'}\n </Typography>\n <BaseDialog\n {...args}\n open={true}\n nonModal={true}\n showActions={true}\n withBottomGutter={false}\n title={args.title}\n >\n <img src={Map} alt='Map sample' />\n </BaseDialog>\n </>\n )\n}"
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
"name": "Small",
|
|
286
|
+
"id": "components-dialogs-dialog--small",
|
|
287
|
+
"code": "import { Alert, Button, Dialog, DialogContent, DialogFooter, DialogHeader, DialogStepper, Typography } from '@carto/meridian-ds/components'\nimport { useTheme } from '@mui/material'\nimport { useState } from 'react'\n\nconst SampleContentSmall = () => (\n <>\n <Typography variant='body2' color='textSecondary'>\n Numeric, string and boolean are supported.\n </Typography>\n\n <div>\n <Alert severity='warning'>\n <Typography variant='code3' component='pre'>\n {someRandomCode}\n </Typography>\n </Alert>\n </div>\n </>\n)\n\nconst BaseDialog = ({\n title,\n chipLabel,\n scrollableContent,\n closeButton,\n children,\n showActions,\n showStepper,\n withGutter = true,\n withBottomGutter = true,\n spacing,\n nonModal = true,\n ...dialogArgs\n}: DialogStoryProps) => {\n const theme = useTheme()\n const [open, setOpen] = useState(false)\n\n const handleClickOpen = (): void => {\n setOpen(!open)\n }\n\n const handleClose = () => setOpen(false)\n\n return (\n <Box\n sx={{\n p: 2,\n backgroundColor: nonModal ? theme.palette.black[12] : 'transparent',\n }}\n >\n {!nonModal && (\n <Button variant='outlined' color='primary' onClick={handleClickOpen}>\n {open ? 'Close' : 'Open'} modal dialog\n </Button>\n )}\n <Dialog\n {...dialogArgs}\n open={open}\n onClose={closeButton ? handleClose : undefined}\n nonModal={nonModal}\n >\n <DialogHeader\n onClose={closeButton ? handleClose : undefined}\n chipLabel={chipLabel}\n title={title}\n >\n {showStepper && (\n <DialogStepper\n currentStep={1}\n stepsLabels={['Step 1', 'Step 2', 'Step 3']}\n />\n )}\n </DialogHeader>\n <DialogContent\n scrollableContent={scrollableContent}\n withGutter={withGutter}\n withBottomGutter={withBottomGutter}\n spacing={spacing}\n >\n {children}\n </DialogContent>\n {showActions && (\n <DialogFooter>\n <Button variant='contained' onClick={handleClose}>\n Done\n </Button>\n </DialogFooter>\n )}\n </Dialog>\n </Box>\n )\n}\n\nconst someRandomCode = `export default {\n title: 'Components/Dialogs/Dialog',\n component: Dialog,\n tags: ['autodocs']\n}\n`\n\nconst Small = ({ explanation, ...args }: DialogStoryProps) => {\n return (\n <>\n {explanation && (\n <Typography variant='subtitle1' color='textSecondary' mb={1}>\n {explanation}\n </Typography>\n )}\n <BaseDialog {...args} nonModal={false}>\n <SampleContentSmall />\n </BaseDialog>\n </>\n )\n}"
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
"name": "Medium",
|
|
291
|
+
"id": "components-dialogs-dialog--medium",
|
|
292
|
+
"code": "import { Alert, Button, Dialog, DialogContent, DialogFooter, DialogHeader, DialogStepper, Typography } from '@carto/meridian-ds/components'\nimport { useTheme } from '@mui/material'\nimport { useState } from 'react'\n\nconst SampleContentSmall = () => (\n <>\n <Typography variant='body2' color='textSecondary'>\n Numeric, string and boolean are supported.\n </Typography>\n\n <div>\n <Alert severity='warning'>\n <Typography variant='code3' component='pre'>\n {someRandomCode}\n </Typography>\n </Alert>\n </div>\n </>\n)\n\nconst BaseDialog = ({\n title,\n chipLabel,\n scrollableContent,\n closeButton,\n children,\n showActions,\n showStepper,\n withGutter = true,\n withBottomGutter = true,\n spacing,\n nonModal = true,\n ...dialogArgs\n}: DialogStoryProps) => {\n const theme = useTheme()\n const [open, setOpen] = useState(false)\n\n const handleClickOpen = (): void => {\n setOpen(!open)\n }\n\n const handleClose = () => setOpen(false)\n\n return (\n <Box\n sx={{\n p: 2,\n backgroundColor: nonModal ? theme.palette.black[12] : 'transparent',\n }}\n >\n {!nonModal && (\n <Button variant='outlined' color='primary' onClick={handleClickOpen}>\n {open ? 'Close' : 'Open'} modal dialog\n </Button>\n )}\n <Dialog\n {...dialogArgs}\n open={open}\n onClose={closeButton ? handleClose : undefined}\n nonModal={nonModal}\n >\n <DialogHeader\n onClose={closeButton ? handleClose : undefined}\n chipLabel={chipLabel}\n title={title}\n >\n {showStepper && (\n <DialogStepper\n currentStep={1}\n stepsLabels={['Step 1', 'Step 2', 'Step 3']}\n />\n )}\n </DialogHeader>\n <DialogContent\n scrollableContent={scrollableContent}\n withGutter={withGutter}\n withBottomGutter={withBottomGutter}\n spacing={spacing}\n >\n {children}\n </DialogContent>\n {showActions && (\n <DialogFooter>\n <Button variant='contained' onClick={handleClose}>\n Done\n </Button>\n </DialogFooter>\n )}\n </Dialog>\n </Box>\n )\n}\n\nconst someRandomCode = `export default {\n title: 'Components/Dialogs/Dialog',\n component: Dialog,\n tags: ['autodocs']\n}\n`\n\nconst Medium = ({ explanation, ...args }: DialogStoryProps) => {\n return (\n <>\n {explanation && (\n <Typography variant='subtitle1' color='textSecondary' mb={1}>\n {explanation}\n </Typography>\n )}\n <BaseDialog {...args} nonModal={false}>\n <SampleContentSmall />\n </BaseDialog>\n </>\n )\n}"
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
"name": "Large",
|
|
296
|
+
"id": "components-dialogs-dialog--large",
|
|
297
|
+
"code": "import { Alert, Button, Dialog, DialogContent, DialogFooter, DialogHeader, DialogStepper, Typography } from '@carto/meridian-ds/components'\nimport { useTheme } from '@mui/material'\nimport { useState } from 'react'\n\nconst SampleContentSmall = () => (\n <>\n <Typography variant='body2' color='textSecondary'>\n Numeric, string and boolean are supported.\n </Typography>\n\n <div>\n <Alert severity='warning'>\n <Typography variant='code3' component='pre'>\n {someRandomCode}\n </Typography>\n </Alert>\n </div>\n </>\n)\n\nconst BaseDialog = ({\n title,\n chipLabel,\n scrollableContent,\n closeButton,\n children,\n showActions,\n showStepper,\n withGutter = true,\n withBottomGutter = true,\n spacing,\n nonModal = true,\n ...dialogArgs\n}: DialogStoryProps) => {\n const theme = useTheme()\n const [open, setOpen] = useState(false)\n\n const handleClickOpen = (): void => {\n setOpen(!open)\n }\n\n const handleClose = () => setOpen(false)\n\n return (\n <Box\n sx={{\n p: 2,\n backgroundColor: nonModal ? theme.palette.black[12] : 'transparent',\n }}\n >\n {!nonModal && (\n <Button variant='outlined' color='primary' onClick={handleClickOpen}>\n {open ? 'Close' : 'Open'} modal dialog\n </Button>\n )}\n <Dialog\n {...dialogArgs}\n open={open}\n onClose={closeButton ? handleClose : undefined}\n nonModal={nonModal}\n >\n <DialogHeader\n onClose={closeButton ? handleClose : undefined}\n chipLabel={chipLabel}\n title={title}\n >\n {showStepper && (\n <DialogStepper\n currentStep={1}\n stepsLabels={['Step 1', 'Step 2', 'Step 3']}\n />\n )}\n </DialogHeader>\n <DialogContent\n scrollableContent={scrollableContent}\n withGutter={withGutter}\n withBottomGutter={withBottomGutter}\n spacing={spacing}\n >\n {children}\n </DialogContent>\n {showActions && (\n <DialogFooter>\n <Button variant='contained' onClick={handleClose}>\n Done\n </Button>\n </DialogFooter>\n )}\n </Dialog>\n </Box>\n )\n}\n\nconst someRandomCode = `export default {\n title: 'Components/Dialogs/Dialog',\n component: Dialog,\n tags: ['autodocs']\n}\n`\n\nconst Large = ({ explanation, ...args }: DialogStoryProps) => {\n return (\n <>\n {explanation && (\n <Typography variant='subtitle1' color='textSecondary' mb={1}>\n {explanation}\n </Typography>\n )}\n <BaseDialog {...args} nonModal={false}>\n <SampleContentSmall />\n </BaseDialog>\n </>\n )\n}"
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
"name": "XLarge",
|
|
301
|
+
"id": "components-dialogs-dialog--xlarge",
|
|
302
|
+
"code": "import { Alert, Button, Dialog, DialogContent, DialogFooter, DialogHeader, DialogStepper, Typography } from '@carto/meridian-ds/components'\nimport { useTheme } from '@mui/material'\nimport { useState } from 'react'\n\nconst SampleContentSmall = () => (\n <>\n <Typography variant='body2' color='textSecondary'>\n Numeric, string and boolean are supported.\n </Typography>\n\n <div>\n <Alert severity='warning'>\n <Typography variant='code3' component='pre'>\n {someRandomCode}\n </Typography>\n </Alert>\n </div>\n </>\n)\n\nconst BaseDialog = ({\n title,\n chipLabel,\n scrollableContent,\n closeButton,\n children,\n showActions,\n showStepper,\n withGutter = true,\n withBottomGutter = true,\n spacing,\n nonModal = true,\n ...dialogArgs\n}: DialogStoryProps) => {\n const theme = useTheme()\n const [open, setOpen] = useState(false)\n\n const handleClickOpen = (): void => {\n setOpen(!open)\n }\n\n const handleClose = () => setOpen(false)\n\n return (\n <Box\n sx={{\n p: 2,\n backgroundColor: nonModal ? theme.palette.black[12] : 'transparent',\n }}\n >\n {!nonModal && (\n <Button variant='outlined' color='primary' onClick={handleClickOpen}>\n {open ? 'Close' : 'Open'} modal dialog\n </Button>\n )}\n <Dialog\n {...dialogArgs}\n open={open}\n onClose={closeButton ? handleClose : undefined}\n nonModal={nonModal}\n >\n <DialogHeader\n onClose={closeButton ? handleClose : undefined}\n chipLabel={chipLabel}\n title={title}\n >\n {showStepper && (\n <DialogStepper\n currentStep={1}\n stepsLabels={['Step 1', 'Step 2', 'Step 3']}\n />\n )}\n </DialogHeader>\n <DialogContent\n scrollableContent={scrollableContent}\n withGutter={withGutter}\n withBottomGutter={withBottomGutter}\n spacing={spacing}\n >\n {children}\n </DialogContent>\n {showActions && (\n <DialogFooter>\n <Button variant='contained' onClick={handleClose}>\n Done\n </Button>\n </DialogFooter>\n )}\n </Dialog>\n </Box>\n )\n}\n\nconst someRandomCode = `export default {\n title: 'Components/Dialogs/Dialog',\n component: Dialog,\n tags: ['autodocs']\n}\n`\n\nconst XLarge = ({ explanation, ...args }: DialogStoryProps) => {\n return (\n <>\n {explanation && (\n <Typography variant='subtitle1' color='textSecondary' mb={1}>\n {explanation}\n </Typography>\n )}\n <BaseDialog {...args} nonModal={false}>\n <SampleContentSmall />\n </BaseDialog>\n </>\n )\n}"
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"name": "FullScreen",
|
|
306
|
+
"id": "components-dialogs-dialog--full-screen",
|
|
307
|
+
"code": "import { Alert, Button, Dialog, DialogContent, DialogFooter, DialogHeader, DialogStepper, Typography } from '@carto/meridian-ds/components'\nimport { useTheme } from '@mui/material'\nimport { useState } from 'react'\n\nconst SampleContentSmall = () => (\n <>\n <Typography variant='body2' color='textSecondary'>\n Numeric, string and boolean are supported.\n </Typography>\n\n <div>\n <Alert severity='warning'>\n <Typography variant='code3' component='pre'>\n {someRandomCode}\n </Typography>\n </Alert>\n </div>\n </>\n)\n\nconst BaseDialog = ({\n title,\n chipLabel,\n scrollableContent,\n closeButton,\n children,\n showActions,\n showStepper,\n withGutter = true,\n withBottomGutter = true,\n spacing,\n nonModal = true,\n ...dialogArgs\n}: DialogStoryProps) => {\n const theme = useTheme()\n const [open, setOpen] = useState(false)\n\n const handleClickOpen = (): void => {\n setOpen(!open)\n }\n\n const handleClose = () => setOpen(false)\n\n return (\n <Box\n sx={{\n p: 2,\n backgroundColor: nonModal ? theme.palette.black[12] : 'transparent',\n }}\n >\n {!nonModal && (\n <Button variant='outlined' color='primary' onClick={handleClickOpen}>\n {open ? 'Close' : 'Open'} modal dialog\n </Button>\n )}\n <Dialog\n {...dialogArgs}\n open={open}\n onClose={closeButton ? handleClose : undefined}\n nonModal={nonModal}\n >\n <DialogHeader\n onClose={closeButton ? handleClose : undefined}\n chipLabel={chipLabel}\n title={title}\n >\n {showStepper && (\n <DialogStepper\n currentStep={1}\n stepsLabels={['Step 1', 'Step 2', 'Step 3']}\n />\n )}\n </DialogHeader>\n <DialogContent\n scrollableContent={scrollableContent}\n withGutter={withGutter}\n withBottomGutter={withBottomGutter}\n spacing={spacing}\n >\n {children}\n </DialogContent>\n {showActions && (\n <DialogFooter>\n <Button variant='contained' onClick={handleClose}>\n Done\n </Button>\n </DialogFooter>\n )}\n </Dialog>\n </Box>\n )\n}\n\nconst someRandomCode = `export default {\n title: 'Components/Dialogs/Dialog',\n component: Dialog,\n tags: ['autodocs']\n}\n`\n\nconst FullScreen = ({ explanation, ...args }: DialogStoryProps) => {\n return (\n <>\n {explanation && (\n <Typography variant='subtitle1' color='textSecondary' mb={1}>\n {explanation}\n </Typography>\n )}\n <BaseDialog {...args} nonModal={false}>\n <SampleContentSmall />\n </BaseDialog>\n </>\n )\n}"
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
"name": "FluidHeight",
|
|
311
|
+
"id": "components-dialogs-dialog--fluid-height",
|
|
312
|
+
"code": "import { Alert, Button, Dialog, DialogContent, DialogFooter, DialogHeader, DialogStepper, Typography } from '@carto/meridian-ds/components'\nimport { useTheme } from '@mui/material'\nimport { useState } from 'react'\n\nconst SampleContentSmall = () => (\n <>\n <Typography variant='body2' color='textSecondary'>\n Numeric, string and boolean are supported.\n </Typography>\n\n <div>\n <Alert severity='warning'>\n <Typography variant='code3' component='pre'>\n {someRandomCode}\n </Typography>\n </Alert>\n </div>\n </>\n)\n\nconst BaseDialog = ({\n title,\n chipLabel,\n scrollableContent,\n closeButton,\n children,\n showActions,\n showStepper,\n withGutter = true,\n withBottomGutter = true,\n spacing,\n nonModal = true,\n ...dialogArgs\n}: DialogStoryProps) => {\n const theme = useTheme()\n const [open, setOpen] = useState(false)\n\n const handleClickOpen = (): void => {\n setOpen(!open)\n }\n\n const handleClose = () => setOpen(false)\n\n return (\n <Box\n sx={{\n p: 2,\n backgroundColor: nonModal ? theme.palette.black[12] : 'transparent',\n }}\n >\n {!nonModal && (\n <Button variant='outlined' color='primary' onClick={handleClickOpen}>\n {open ? 'Close' : 'Open'} modal dialog\n </Button>\n )}\n <Dialog\n {...dialogArgs}\n open={open}\n onClose={closeButton ? handleClose : undefined}\n nonModal={nonModal}\n >\n <DialogHeader\n onClose={closeButton ? handleClose : undefined}\n chipLabel={chipLabel}\n title={title}\n >\n {showStepper && (\n <DialogStepper\n currentStep={1}\n stepsLabels={['Step 1', 'Step 2', 'Step 3']}\n />\n )}\n </DialogHeader>\n <DialogContent\n scrollableContent={scrollableContent}\n withGutter={withGutter}\n withBottomGutter={withBottomGutter}\n spacing={spacing}\n >\n {children}\n </DialogContent>\n {showActions && (\n <DialogFooter>\n <Button variant='contained' onClick={handleClose}>\n Done\n </Button>\n </DialogFooter>\n )}\n </Dialog>\n </Box>\n )\n}\n\nconst someRandomCode = `export default {\n title: 'Components/Dialogs/Dialog',\n component: Dialog,\n tags: ['autodocs']\n}\n`\n\nconst FluidHeight = ({ explanation, ...args }: DialogStoryProps) => {\n return (\n <>\n {explanation && (\n <Typography variant='subtitle1' color='textSecondary' mb={1}>\n {explanation}\n </Typography>\n )}\n <BaseDialog {...args} nonModal={false}>\n <SampleContentSmall />\n </BaseDialog>\n </>\n )\n}"
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
"name": "FluidWidth",
|
|
316
|
+
"id": "components-dialogs-dialog--fluid-width",
|
|
317
|
+
"code": "import { Alert, Button, Dialog, DialogContent, DialogFooter, DialogHeader, DialogStepper, Typography } from '@carto/meridian-ds/components'\nimport { useTheme } from '@mui/material'\nimport { useState } from 'react'\n\nconst SampleContentSmall = () => (\n <>\n <Typography variant='body2' color='textSecondary'>\n Numeric, string and boolean are supported.\n </Typography>\n\n <div>\n <Alert severity='warning'>\n <Typography variant='code3' component='pre'>\n {someRandomCode}\n </Typography>\n </Alert>\n </div>\n </>\n)\n\nconst BaseDialog = ({\n title,\n chipLabel,\n scrollableContent,\n closeButton,\n children,\n showActions,\n showStepper,\n withGutter = true,\n withBottomGutter = true,\n spacing,\n nonModal = true,\n ...dialogArgs\n}: DialogStoryProps) => {\n const theme = useTheme()\n const [open, setOpen] = useState(false)\n\n const handleClickOpen = (): void => {\n setOpen(!open)\n }\n\n const handleClose = () => setOpen(false)\n\n return (\n <Box\n sx={{\n p: 2,\n backgroundColor: nonModal ? theme.palette.black[12] : 'transparent',\n }}\n >\n {!nonModal && (\n <Button variant='outlined' color='primary' onClick={handleClickOpen}>\n {open ? 'Close' : 'Open'} modal dialog\n </Button>\n )}\n <Dialog\n {...dialogArgs}\n open={open}\n onClose={closeButton ? handleClose : undefined}\n nonModal={nonModal}\n >\n <DialogHeader\n onClose={closeButton ? handleClose : undefined}\n chipLabel={chipLabel}\n title={title}\n >\n {showStepper && (\n <DialogStepper\n currentStep={1}\n stepsLabels={['Step 1', 'Step 2', 'Step 3']}\n />\n )}\n </DialogHeader>\n <DialogContent\n scrollableContent={scrollableContent}\n withGutter={withGutter}\n withBottomGutter={withBottomGutter}\n spacing={spacing}\n >\n {children}\n </DialogContent>\n {showActions && (\n <DialogFooter>\n <Button variant='contained' onClick={handleClose}>\n Done\n </Button>\n </DialogFooter>\n )}\n </Dialog>\n </Box>\n )\n}\n\nconst someRandomCode = `export default {\n title: 'Components/Dialogs/Dialog',\n component: Dialog,\n tags: ['autodocs']\n}\n`\n\nconst FluidWidth = ({ explanation, ...args }: DialogStoryProps) => {\n return (\n <>\n {explanation && (\n <Typography variant='subtitle1' color='textSecondary' mb={1}>\n {explanation}\n </Typography>\n )}\n <BaseDialog {...args} nonModal={false}>\n <SampleContentSmall />\n </BaseDialog>\n </>\n )\n}"
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
"name": "WithStepperAndChip",
|
|
321
|
+
"id": "components-dialogs-dialog--with-stepper-and-chip",
|
|
322
|
+
"code": "import { Alert, Button, Dialog, DialogContent, DialogFooter, DialogHeader, DialogStepper, Typography } from '@carto/meridian-ds/components'\nimport { useTheme } from '@mui/material'\nimport { useState } from 'react'\n\nconst SampleContentSmall = () => (\n <>\n <Typography variant='body2' color='textSecondary'>\n Numeric, string and boolean are supported.\n </Typography>\n\n <div>\n <Alert severity='warning'>\n <Typography variant='code3' component='pre'>\n {someRandomCode}\n </Typography>\n </Alert>\n </div>\n </>\n)\n\nconst BaseDialog = ({\n title,\n chipLabel,\n scrollableContent,\n closeButton,\n children,\n showActions,\n showStepper,\n withGutter = true,\n withBottomGutter = true,\n spacing,\n nonModal = true,\n ...dialogArgs\n}: DialogStoryProps) => {\n const theme = useTheme()\n const [open, setOpen] = useState(false)\n\n const handleClickOpen = (): void => {\n setOpen(!open)\n }\n\n const handleClose = () => setOpen(false)\n\n return (\n <Box\n sx={{\n p: 2,\n backgroundColor: nonModal ? theme.palette.black[12] : 'transparent',\n }}\n >\n {!nonModal && (\n <Button variant='outlined' color='primary' onClick={handleClickOpen}>\n {open ? 'Close' : 'Open'} modal dialog\n </Button>\n )}\n <Dialog\n {...dialogArgs}\n open={open}\n onClose={closeButton ? handleClose : undefined}\n nonModal={nonModal}\n >\n <DialogHeader\n onClose={closeButton ? handleClose : undefined}\n chipLabel={chipLabel}\n title={title}\n >\n {showStepper && (\n <DialogStepper\n currentStep={1}\n stepsLabels={['Step 1', 'Step 2', 'Step 3']}\n />\n )}\n </DialogHeader>\n <DialogContent\n scrollableContent={scrollableContent}\n withGutter={withGutter}\n withBottomGutter={withBottomGutter}\n spacing={spacing}\n >\n {children}\n </DialogContent>\n {showActions && (\n <DialogFooter>\n <Button variant='contained' onClick={handleClose}>\n Done\n </Button>\n </DialogFooter>\n )}\n </Dialog>\n </Box>\n )\n}\n\nconst someRandomCode = `export default {\n title: 'Components/Dialogs/Dialog',\n component: Dialog,\n tags: ['autodocs']\n}\n`\n\nconst WithStepperAndChip = (args: DialogStoryProps) => {\n return (\n <BaseDialog\n {...args}\n nonModal={true}\n showStepper={true}\n showActions={true}\n title={args.title}\n chipLabel={args.chipLabel}\n chipProps={args.chipProps}\n >\n <Box>\n This is step <strong>{args.step}</strong> of {args.title}\n </Box>\n <SampleContentSmall />\n </BaseDialog>\n )\n}"
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
"name": "ScrollableContent",
|
|
326
|
+
"id": "components-dialogs-dialog--scrollable-content",
|
|
327
|
+
"code": "import { Alert, Button, Dialog, DialogContent, DialogFooter, DialogHeader, DialogStepper, Typography } from '@carto/meridian-ds/components'\nimport { useTheme } from '@mui/material'\nimport { useState } from 'react'\n\nconst BaseDialog = ({\n title,\n chipLabel,\n scrollableContent,\n closeButton,\n children,\n showActions,\n showStepper,\n withGutter = true,\n withBottomGutter = true,\n spacing,\n nonModal = true,\n ...dialogArgs\n}: DialogStoryProps) => {\n const theme = useTheme()\n const [open, setOpen] = useState(false)\n\n const handleClickOpen = (): void => {\n setOpen(!open)\n }\n\n const handleClose = () => setOpen(false)\n\n return (\n <Box\n sx={{\n p: 2,\n backgroundColor: nonModal ? theme.palette.black[12] : 'transparent',\n }}\n >\n {!nonModal && (\n <Button variant='outlined' color='primary' onClick={handleClickOpen}>\n {open ? 'Close' : 'Open'} modal dialog\n </Button>\n )}\n <Dialog\n {...dialogArgs}\n open={open}\n onClose={closeButton ? handleClose : undefined}\n nonModal={nonModal}\n >\n <DialogHeader\n onClose={closeButton ? handleClose : undefined}\n chipLabel={chipLabel}\n title={title}\n >\n {showStepper && (\n <DialogStepper\n currentStep={1}\n stepsLabels={['Step 1', 'Step 2', 'Step 3']}\n />\n )}\n </DialogHeader>\n <DialogContent\n scrollableContent={scrollableContent}\n withGutter={withGutter}\n withBottomGutter={withBottomGutter}\n spacing={spacing}\n >\n {children}\n </DialogContent>\n {showActions && (\n <DialogFooter>\n <Button variant='contained' onClick={handleClose}>\n Done\n </Button>\n </DialogFooter>\n )}\n </Dialog>\n </Box>\n )\n}\n\nconst someRandomText = (\n <Typography variant='body2' color='textSecondary'>\n Numeric, string and boolean are supported. Date and timestamps will be\n encoded as strings. Learn more about tilesets in our documentation.\n </Typography>\n)\n\nconst someBigRandomLog = `2023-10-13 11:54:35.526 [info] > git config --get commit.template [8ms]\n2023-10-13 11:54:35.560 [info] > git for-each-ref --format=%(refname)%00%(upstream:short)%00%(objectname)%00%(upstream:track)%00%(upstream:remotename)%00%(upstream:remoteref) --ignore-case refs/heads/zbigg/server-data-export-ui refs/remotes/zbigg/server-data-export-ui [39ms]\n2023-10-13 11:54:35.651 [info] > git status -z -uall [91ms]\n2023-10-13 11:54:36.770 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/common/utils/urlUtils.ts [23ms]\n2023-10-13 11:54:36.770 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/jobs/ui/JobItem/DownloadsPart.tsx [28ms]\n2023-10-13 11:54:36.770 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/jobs/ui/JobItem/DownloadsDialog.tsx [33ms]\n2023-10-13 11:54:36.770 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/Makefile [52ms]\n2023-10-13 11:54:36.770 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/jobs-samples.md [53ms]\n2023-10-13 11:54:36.770 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/time-series-fixes-and-enchancements.md [54ms]\n2023-10-13 11:54:36.772 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/access-token/ui/AccessTokenForm/AccessTokenFormApi/AccessTokenFormApiOptions.tsx [25ms]\n2023-10-13 11:54:36.772 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/data-explorer/ui/Resources/Actions/Subscription/SubscriptionExportDialog/SubscriptionExportDialogContent/JobSuccessDownload.tsx [26ms]\n2023-10-13 11:54:36.773 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/common/ui/utils/CopiableComponent.tsx [28ms]\n2023-10-13 11:54:36.773 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/common/utils/dateFormat.ts [28ms]\n2023-10-13 11:54:36.775 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/jobs/ui/JobItem/ErrorDetailsDialog.tsx [34ms]\n2023-10-13 11:54:36.775 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/__tests__/features/jobs/mocks/processingJobs.ts [41ms]\n2023-10-13 11:54:36.781 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/jobs/state/jobsExportingSlice.ts [48ms]\n2023-10-13 11:54:36.781 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/metrics/state/metricsSagas.ts [48ms]\n2023-10-13 11:54:36.782 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/analysis/ui/NewAnalysisDialog/AnalysisCatalog/Buffer/Form/TractsDropdown.tsx [54ms]\n2023-10-13 11:54:36.783 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/jobs/models/exportsModel.ts [52ms]\n2023-10-13 11:54:36.784 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/data-explorer/ui/Resources/Actions/Subscription/SubscriptionExportDialog/useExportHooks.ts [53ms]\n2023-10-13 11:54:36.786 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/builder/ui/BuilderPrivate/BuilderHeader/BuilderHeaderActions/ExportDataDialog.tsx [63ms]\n2023-10-13 11:54:36.787 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/accounts-www/src/features/accounts/ui/Form/FormSelect.tsx [62ms]\n2023-10-13 11:54:36.787 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/jobs/ui/JobsPopper.tsx [67ms]\n2023-10-13 11:54:36.788 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/common/ui/AppTemplate/HeaderBase/Partials/JobsStatusIndicator.`\n\nconst someRandomLogElement = (\n <Typography variant='code3' component='pre'>\n {someBigRandomLog}\n </Typography>\n)\n\nconst ScrollableContent = (args: DialogStoryProps) => (\n <BaseDialog {...args} nonModal scrollableContent showActions closeButton>\n {someRandomText}\n <div>\n <Alert severity='warning'>{someRandomLogElement}</Alert>\n </div>\n </BaseDialog>\n)"
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
"name": "InternallScroll",
|
|
331
|
+
"id": "components-dialogs-dialog--internall-scroll",
|
|
332
|
+
"code": "import { Alert, Button, Dialog, DialogContent, DialogFooter, DialogHeader, DialogStepper, Typography } from '@carto/meridian-ds/components'\nimport { useTheme } from '@mui/material'\nimport { useState } from 'react'\n\nconst BaseDialog = ({\n title,\n chipLabel,\n scrollableContent,\n closeButton,\n children,\n showActions,\n showStepper,\n withGutter = true,\n withBottomGutter = true,\n spacing,\n nonModal = true,\n ...dialogArgs\n}: DialogStoryProps) => {\n const theme = useTheme()\n const [open, setOpen] = useState(false)\n\n const handleClickOpen = (): void => {\n setOpen(!open)\n }\n\n const handleClose = () => setOpen(false)\n\n return (\n <Box\n sx={{\n p: 2,\n backgroundColor: nonModal ? theme.palette.black[12] : 'transparent',\n }}\n >\n {!nonModal && (\n <Button variant='outlined' color='primary' onClick={handleClickOpen}>\n {open ? 'Close' : 'Open'} modal dialog\n </Button>\n )}\n <Dialog\n {...dialogArgs}\n open={open}\n onClose={closeButton ? handleClose : undefined}\n nonModal={nonModal}\n >\n <DialogHeader\n onClose={closeButton ? handleClose : undefined}\n chipLabel={chipLabel}\n title={title}\n >\n {showStepper && (\n <DialogStepper\n currentStep={1}\n stepsLabels={['Step 1', 'Step 2', 'Step 3']}\n />\n )}\n </DialogHeader>\n <DialogContent\n scrollableContent={scrollableContent}\n withGutter={withGutter}\n withBottomGutter={withBottomGutter}\n spacing={spacing}\n >\n {children}\n </DialogContent>\n {showActions && (\n <DialogFooter>\n <Button variant='contained' onClick={handleClose}>\n Done\n </Button>\n </DialogFooter>\n )}\n </Dialog>\n </Box>\n )\n}\n\nconst someRandomText = (\n <Typography variant='body2' color='textSecondary'>\n Numeric, string and boolean are supported. Date and timestamps will be\n encoded as strings. Learn more about tilesets in our documentation.\n </Typography>\n)\n\nconst someBigRandomLog = `2023-10-13 11:54:35.526 [info] > git config --get commit.template [8ms]\n2023-10-13 11:54:35.560 [info] > git for-each-ref --format=%(refname)%00%(upstream:short)%00%(objectname)%00%(upstream:track)%00%(upstream:remotename)%00%(upstream:remoteref) --ignore-case refs/heads/zbigg/server-data-export-ui refs/remotes/zbigg/server-data-export-ui [39ms]\n2023-10-13 11:54:35.651 [info] > git status -z -uall [91ms]\n2023-10-13 11:54:36.770 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/common/utils/urlUtils.ts [23ms]\n2023-10-13 11:54:36.770 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/jobs/ui/JobItem/DownloadsPart.tsx [28ms]\n2023-10-13 11:54:36.770 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/jobs/ui/JobItem/DownloadsDialog.tsx [33ms]\n2023-10-13 11:54:36.770 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/Makefile [52ms]\n2023-10-13 11:54:36.770 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/jobs-samples.md [53ms]\n2023-10-13 11:54:36.770 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/time-series-fixes-and-enchancements.md [54ms]\n2023-10-13 11:54:36.772 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/access-token/ui/AccessTokenForm/AccessTokenFormApi/AccessTokenFormApiOptions.tsx [25ms]\n2023-10-13 11:54:36.772 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/data-explorer/ui/Resources/Actions/Subscription/SubscriptionExportDialog/SubscriptionExportDialogContent/JobSuccessDownload.tsx [26ms]\n2023-10-13 11:54:36.773 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/common/ui/utils/CopiableComponent.tsx [28ms]\n2023-10-13 11:54:36.773 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/common/utils/dateFormat.ts [28ms]\n2023-10-13 11:54:36.775 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/jobs/ui/JobItem/ErrorDetailsDialog.tsx [34ms]\n2023-10-13 11:54:36.775 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/__tests__/features/jobs/mocks/processingJobs.ts [41ms]\n2023-10-13 11:54:36.781 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/jobs/state/jobsExportingSlice.ts [48ms]\n2023-10-13 11:54:36.781 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/metrics/state/metricsSagas.ts [48ms]\n2023-10-13 11:54:36.782 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/analysis/ui/NewAnalysisDialog/AnalysisCatalog/Buffer/Form/TractsDropdown.tsx [54ms]\n2023-10-13 11:54:36.783 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/jobs/models/exportsModel.ts [52ms]\n2023-10-13 11:54:36.784 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/data-explorer/ui/Resources/Actions/Subscription/SubscriptionExportDialog/useExportHooks.ts [53ms]\n2023-10-13 11:54:36.786 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/builder/ui/BuilderPrivate/BuilderHeader/BuilderHeaderActions/ExportDataDialog.tsx [63ms]\n2023-10-13 11:54:36.787 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/accounts-www/src/features/accounts/ui/Form/FormSelect.tsx [62ms]\n2023-10-13 11:54:36.787 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/jobs/ui/JobsPopper.tsx [67ms]\n2023-10-13 11:54:36.788 [info] > git ls-files --stage -- /Users/zbigg/carto/cloud-native/workspace-www/src/features/common/ui/AppTemplate/HeaderBase/Partials/JobsStatusIndicator.`\n\nconst someRandomLogElement = (\n <Typography variant='code3' component='pre'>\n {someBigRandomLog}\n </Typography>\n)\n\nconst InternallScroll = (args: DialogStoryProps) => (\n <BaseDialog {...args} nonModal showActions closeButton>\n {someRandomText}\n <Box style={{ maxHeight: 'fit-content', overflowY: 'scroll' }}>\n <Alert severity='warning'>{someRandomLogElement}</Alert>\n </Box>\n </BaseDialog>\n)"
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
"name": "CustomSpacing",
|
|
336
|
+
"id": "components-dialogs-dialog--custom-spacing",
|
|
337
|
+
"code": "import { Alert, Button, Dialog, DialogContent, DialogFooter, DialogHeader, DialogStepper, Typography } from '@carto/meridian-ds/components'\nimport { useTheme } from '@mui/material'\nimport { useState } from 'react'\n\nconst SampleContentSmall = () => (\n <>\n <Typography variant='body2' color='textSecondary'>\n Numeric, string and boolean are supported.\n </Typography>\n\n <div>\n <Alert severity='warning'>\n <Typography variant='code3' component='pre'>\n {someRandomCode}\n </Typography>\n </Alert>\n </div>\n </>\n)\n\nconst BaseDialog = ({\n title,\n chipLabel,\n scrollableContent,\n closeButton,\n children,\n showActions,\n showStepper,\n withGutter = true,\n withBottomGutter = true,\n spacing,\n nonModal = true,\n ...dialogArgs\n}: DialogStoryProps) => {\n const theme = useTheme()\n const [open, setOpen] = useState(false)\n\n const handleClickOpen = (): void => {\n setOpen(!open)\n }\n\n const handleClose = () => setOpen(false)\n\n return (\n <Box\n sx={{\n p: 2,\n backgroundColor: nonModal ? theme.palette.black[12] : 'transparent',\n }}\n >\n {!nonModal && (\n <Button variant='outlined' color='primary' onClick={handleClickOpen}>\n {open ? 'Close' : 'Open'} modal dialog\n </Button>\n )}\n <Dialog\n {...dialogArgs}\n open={open}\n onClose={closeButton ? handleClose : undefined}\n nonModal={nonModal}\n >\n <DialogHeader\n onClose={closeButton ? handleClose : undefined}\n chipLabel={chipLabel}\n title={title}\n >\n {showStepper && (\n <DialogStepper\n currentStep={1}\n stepsLabels={['Step 1', 'Step 2', 'Step 3']}\n />\n )}\n </DialogHeader>\n <DialogContent\n scrollableContent={scrollableContent}\n withGutter={withGutter}\n withBottomGutter={withBottomGutter}\n spacing={spacing}\n >\n {children}\n </DialogContent>\n {showActions && (\n <DialogFooter>\n <Button variant='contained' onClick={handleClose}>\n Done\n </Button>\n </DialogFooter>\n )}\n </Dialog>\n </Box>\n )\n}\n\nconst someRandomCode = `export default {\n title: 'Components/Dialogs/Dialog',\n component: Dialog,\n tags: ['autodocs']\n}\n`\n\nconst CustomSpacing = (args: DialogStoryProps) => {\n return (\n <BaseDialog {...args}>\n <SampleContentSmall />\n </BaseDialog>\n )\n}"
|
|
338
|
+
}
|
|
339
|
+
]
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
"name": "IconButton",
|
|
343
|
+
"description": "Compact icon-only button for actions where a label would add noise (toolbars, table rows, close affordances). Supports tooltip, loading state, and multiple visual variants. Always provide an accessible label via tooltip or aria-label.",
|
|
344
|
+
"curation": {
|
|
345
|
+
"keywords": [
|
|
346
|
+
"icon action",
|
|
347
|
+
"icon click",
|
|
348
|
+
"toolbar button",
|
|
349
|
+
"delete icon",
|
|
350
|
+
"edit icon",
|
|
351
|
+
"round button"
|
|
352
|
+
],
|
|
353
|
+
"mui": [
|
|
354
|
+
"color",
|
|
355
|
+
"disabled",
|
|
356
|
+
"size"
|
|
357
|
+
],
|
|
358
|
+
"decisionTree": [
|
|
359
|
+
{
|
|
360
|
+
"condition": "Action needs a text label for clarity",
|
|
361
|
+
"use": "Button"
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
"condition": "Toggle state (on/off, active/inactive)",
|
|
365
|
+
"use": "ToggleButton",
|
|
366
|
+
"isMUI": true
|
|
367
|
+
}
|
|
368
|
+
]
|
|
369
|
+
},
|
|
370
|
+
"examples": [
|
|
371
|
+
{
|
|
372
|
+
"name": "Playground",
|
|
373
|
+
"id": "components-buttons-iconbutton--playground",
|
|
374
|
+
"code": "import { IconButton, IconButtonProps } from '@carto/meridian-ds/components'\n\nconst Playground = ({ size, color, ...rest }: IconButtonProps) => (\n <IconButton\n {...rest}\n color={color}\n size={size}\n icon={<CheckCircleOutlined />}\n />\n)"
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
"name": "Tooltip",
|
|
378
|
+
"id": "components-buttons-iconbutton--tooltip",
|
|
379
|
+
"code": "import { IconButton, IconButtonProps, Typography } from '@carto/meridian-ds/components'\n\nconst SizeTemplate = (rest: IconButtonProps) => {\n return (\n <Grid container spacing={2}>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Icon\n </Typography>\n <IconButton {...rest} variant='icon' icon={<CheckCircleOutlined />} />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Contained\n </Typography>\n <IconButton\n {...rest}\n variant='contained'\n icon={<CheckCircleOutlined />}\n />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Outlined\n </Typography>\n <IconButton\n {...rest}\n variant='outlined'\n icon={<CheckCircleOutlined />}\n />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Disabled\n </Typography>\n <IconButton {...rest} disabled icon={<CheckCircleOutlined />} />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Loading\n </Typography>\n <IconButton {...rest} loading icon={<CheckCircleOutlined />} />\n </Grid>\n </Grid>\n </Grid>\n )\n}\n\nconst tooltipConfigs: {\n label: string\n args: Partial<IconButtonProps>\n}[] = [\n {\n label: 'Default placement (top)',\n args: { tooltip: 'Tooltip text' },\n },\n {\n label: 'Custom placement (bottom)',\n args: { tooltip: 'Tooltip text', tooltipPlacement: 'bottom' },\n },\n {\n label: 'Disabled',\n args: { tooltip: 'Tooltip text', disabled: true },\n },\n]\n\nconst Tooltip = (rest: IconButtonProps) => (\n <>\n {tooltipConfigs.map(({ label, args }) => (\n <Box key={label} mb={6}>\n <Typography variant='h6' sx={{ mb: 4 }}>\n {label}\n </Typography>\n <SizeTemplate {...rest} {...args} />\n </Box>\n ))}\n </>\n)"
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
"name": "Variants",
|
|
383
|
+
"id": "components-buttons-iconbutton--variants",
|
|
384
|
+
"code": "import { IconButton, IconButtonProps, Typography } from '@carto/meridian-ds/components'\n\nconst Variants = (rest: IconButtonProps) => {\n return (\n <>\n <Typography variant='h6' sx={{ mb: 4 }}>\n Icon (default)\n </Typography>\n <Grid container spacing={2}>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n XSmall\n </Typography>\n <IconButton\n {...rest}\n size='xsmall'\n icon={<CheckCircleOutlined />}\n />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Small\n </Typography>\n <IconButton {...rest} size='small' icon={<CheckCircleOutlined />} />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Medium\n </Typography>\n <IconButton\n {...rest}\n size='medium'\n icon={<CheckCircleOutlined />}\n />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Large\n </Typography>\n <IconButton {...rest} size='large' icon={<CheckCircleOutlined />} />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Disabled\n </Typography>\n <IconButton {...rest} disabled icon={<CheckCircleOutlined />} />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Loading\n </Typography>\n <IconButton {...rest} loading icon={<CheckCircleOutlined />} />\n </Grid>\n </Grid>\n </Grid>\n <Typography variant='h6' sx={{ mb: 4, mt: 6 }}>\n Contained\n </Typography>\n <Grid container spacing={2}>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n XSmall\n </Typography>\n <IconButton\n {...rest}\n variant='contained'\n size='xsmall'\n icon={<CheckCircleOutlined />}\n />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Small\n </Typography>\n <IconButton\n {...rest}\n variant='contained'\n size='small'\n icon={<CheckCircleOutlined />}\n />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Medium\n </Typography>\n <IconButton\n {...rest}\n variant='contained'\n size='medium'\n icon={<CheckCircleOutlined />}\n />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Large\n </Typography>\n <IconButton\n {...rest}\n variant='contained'\n size='large'\n icon={<CheckCircleOutlined />}\n />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Disabled\n </Typography>\n <IconButton\n {...rest}\n variant='contained'\n disabled\n icon={<CheckCircleOutlined />}\n />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Loading\n </Typography>\n <IconButton\n {...rest}\n variant='contained'\n loading\n icon={<CheckCircleOutlined />}\n />\n </Grid>\n </Grid>\n </Grid>\n <Typography variant='h6' sx={{ mb: 4, mt: 6 }}>\n Outlined\n </Typography>\n <Grid container spacing={2}>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n XSmall\n </Typography>\n <IconButton\n {...rest}\n variant='outlined'\n size='xsmall'\n icon={<CheckCircleOutlined />}\n />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Small\n </Typography>\n <IconButton\n {...rest}\n variant='outlined'\n size='small'\n icon={<CheckCircleOutlined />}\n />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Medium\n </Typography>\n <IconButton\n {...rest}\n variant='outlined'\n size='medium'\n icon={<CheckCircleOutlined />}\n />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Large\n </Typography>\n <IconButton\n {...rest}\n variant='outlined'\n size='large'\n icon={<CheckCircleOutlined />}\n />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Disabled\n </Typography>\n <IconButton\n {...rest}\n variant='outlined'\n disabled\n icon={<CheckCircleOutlined />}\n />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Loading\n </Typography>\n <IconButton\n {...rest}\n variant='outlined'\n loading\n icon={<CheckCircleOutlined />}\n />\n </Grid>\n </Grid>\n </Grid>\n </>\n )\n}"
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
"name": "Colors",
|
|
388
|
+
"id": "components-buttons-iconbutton--colors",
|
|
389
|
+
"code": "import { IconButton, IconButtonProps, Typography } from '@carto/meridian-ds/components'\n\nconst SizeTemplate = (rest: IconButtonProps) => {\n return (\n <Grid container spacing={2}>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Icon\n </Typography>\n <IconButton {...rest} variant='icon' icon={<CheckCircleOutlined />} />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Contained\n </Typography>\n <IconButton\n {...rest}\n variant='contained'\n icon={<CheckCircleOutlined />}\n />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Outlined\n </Typography>\n <IconButton\n {...rest}\n variant='outlined'\n icon={<CheckCircleOutlined />}\n />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Disabled\n </Typography>\n <IconButton {...rest} disabled icon={<CheckCircleOutlined />} />\n </Grid>\n </Grid>\n <Grid item xs={2}>\n <Grid container direction='column' alignItems='center' spacing={2}>\n <Typography variant='body2' sx={{ mb: 2 }}>\n Loading\n </Typography>\n <IconButton {...rest} loading icon={<CheckCircleOutlined />} />\n </Grid>\n </Grid>\n </Grid>\n )\n}\n\nconst colors = ['default', 'primary', 'secondary', 'error', 'warning'] as const\n\nconst Colors = (rest: IconButtonProps) => (\n <>\n {colors.map((color) => (\n <Box key={color} mb={6}>\n <Typography variant='h6' sx={{ mb: 4, textTransform: 'capitalize' }}>\n {color}\n </Typography>\n <SizeTemplate {...rest} color={color} />\n </Box>\n ))}\n </>\n)"
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
"name": "IconButtonGroup",
|
|
393
|
+
"id": "components-buttons-iconbutton--icon-button-group",
|
|
394
|
+
"code": "import { IconButton, Typography } from '@carto/meridian-ds/components'\n\nconst IconButtonGroup = () => (\n <>\n <Typography variant='h6' sx={{ mb: 2 }}>\n Icon Button Group\n </Typography>\n <Typography variant='body2' sx={{ mb: 3 }}>\n Use Stack to group related icon buttons with consistent spacing.\n </Typography>\n <Stack direction='row' spacing={1}>\n <IconButton icon={<EditOutlined />} tooltip='Edit' />\n <IconButton icon={<ContentCopyOutlined />} tooltip='Copy' />\n <IconButton icon={<DeleteOutline />} tooltip='Delete' color='error' />\n </Stack>\n </>\n)"
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
"name": "AccessibilityGuide",
|
|
398
|
+
"id": "components-buttons-iconbutton--accessibility-guide",
|
|
399
|
+
"code": "import { CodeAreaField, IconButton, Typography } from '@carto/meridian-ds/components'\n\nconst AccessibilityGuide = () => {\n const code = `// ✅ Good - tests using accessible name\nexpect(screen.getByRole('button', { name: 'Updated' })).toBeVisible()\n\n// ❌ Avoid - relies on implementation details\nexpect(screen.getByTestId('CheckCircleOutlinedIcon')).toBeVisible()`\n\n return (\n <>\n <Typography variant='h6' sx={{ mb: 2 }}>\n Accessibility Guidelines\n </Typography>\n <Typography variant='body2' sx={{ mb: 3 }}>\n IconButtons must have accessible labels for screen readers. Use the{' '}\n <i>aria-label</i> prop to provide descriptive text.\n </Typography>\n\n <Typography variant='h6' sx={{ mb: 2, mt: 4 }}>\n Good Example\n </Typography>\n <Box>\n <IconButton\n icon={<CheckCircleOutlined />}\n aria-label='Updated'\n variant='outlined'\n />\n <Typography variant='caption' display='block' sx={{ mt: 1 }}>\n aria-label="Updated"\n </Typography>\n </Box>\n\n <Typography variant='h6' sx={{ mb: 2, mt: 4 }}>\n Unit Testing\n </Typography>\n <CodeAreaField\n label='Test IconButtons using their accessible name'\n options={{ readOnly: true, mode: 'javascript' }}\n copyValue={code}\n value={code}\n />\n </>\n )\n}"
|
|
400
|
+
}
|
|
401
|
+
]
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
"name": "SelectField",
|
|
405
|
+
"description": "Dropdown select for picking one value from a short list (typically under 10 options). Includes integrated label, helper text, and placeholder.",
|
|
406
|
+
"curation": {
|
|
407
|
+
"keywords": [
|
|
408
|
+
"select input",
|
|
409
|
+
"option picker",
|
|
410
|
+
"single selection",
|
|
411
|
+
"pick one item"
|
|
412
|
+
],
|
|
413
|
+
"mui": [
|
|
414
|
+
"value",
|
|
415
|
+
"onChange",
|
|
416
|
+
{
|
|
417
|
+
"name": "label",
|
|
418
|
+
"aiHint": "Always provide either label (visible) or aria-label (screen-reader-only); a select without an accessible name fails a11y."
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
"name": "children",
|
|
422
|
+
"aiHint": "Use MenuItem from @mui/material or Meridian. Each needs a unique 'value' prop. Group related options with ListSubheader if needed."
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
"name": "displayEmpty",
|
|
426
|
+
"aiHint": "Automatically set to true when placeholder is provided"
|
|
427
|
+
},
|
|
428
|
+
"disabled",
|
|
429
|
+
"error",
|
|
430
|
+
"required"
|
|
431
|
+
],
|
|
432
|
+
"decisionTree": [
|
|
433
|
+
{
|
|
434
|
+
"condition": ">10 items or search needed",
|
|
435
|
+
"use": "Autocomplete"
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
"condition": "Users need to create options not in the predefined list",
|
|
439
|
+
"use": "CreatableAutocomplete"
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
"condition": "Multiple selection, 2-5 options always visible",
|
|
443
|
+
"use": "Checkbox",
|
|
444
|
+
"isMUI": true,
|
|
445
|
+
"aiHint": "Prefer when options benefit from always being visible. Use MultipleSelectField instead when saving vertical space matters."
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
"condition": "Multiple selection",
|
|
449
|
+
"use": "MultipleSelectField"
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
"condition": "2-5 always-visible options in a form, single selection",
|
|
453
|
+
"use": "RadioGroup",
|
|
454
|
+
"isMUI": true,
|
|
455
|
+
"aiHint": "Prefer when options benefit from always being visible or need per-option descriptions. Use SelectField instead when saving vertical space matters."
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
"condition": "2-5 options in a toolbar with icons",
|
|
459
|
+
"use": "ToggleButtonGroup",
|
|
460
|
+
"aiHint": "Compact, supports icons, good for mode toggles (e.g., grid/list view)"
|
|
461
|
+
},
|
|
462
|
+
{
|
|
463
|
+
"condition": "Large list of options needing search",
|
|
464
|
+
"use": "Autocomplete",
|
|
465
|
+
"aiHint": "SelectField has no search; switch to Autocomplete past ~10 options."
|
|
466
|
+
}
|
|
467
|
+
]
|
|
468
|
+
},
|
|
469
|
+
"examples": [
|
|
470
|
+
{
|
|
471
|
+
"name": "Playground",
|
|
472
|
+
"id": "components-select-field-select-field--playground",
|
|
473
|
+
"code": "import { MenuItem, SelectField } from '@carto/meridian-ds/components'\nimport { SelectChangeEvent } from '@mui/material'\nimport { useState } from 'react'\n\nconst menuItems = [\n { label: 'Ten: super large text with overflow', id: '10' },\n { label: 'Twenty', id: '20' },\n { label: 'Thirty', id: '30' },\n]\n\nconst SelectFieldItem = ({\n label,\n required,\n placeholder,\n variant,\n helperText,\n size,\n focused,\n disabled,\n error,\n ...rest\n}: SelectFieldProps) => {\n const [content, setContent] = useState([] as string[])\n\n const handleChange = (event: SelectChangeEvent<unknown>) => {\n const value = event.target.value\n setContent(\n // On autofill we get a stringified value\n typeof value === 'string' ? value.split(',') : (value as string[]),\n )\n }\n\n return (\n <SelectField\n {...rest}\n variant={variant}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n value={content}\n focused={focused}\n disabled={disabled}\n onChange={handleChange}\n error={error}\n size={size}\n fullWidth={rest.fullWidth}\n required={required}\n >\n {menuItems.map((o, i) => (\n <MenuItem key={i} value={o.label}>\n {o.label}\n </MenuItem>\n ))}\n </SelectField>\n )\n}\n\nconst Playground = (args: SelectFieldProps) => (\n <SelectFieldItem {...args} />\n)"
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
"name": "Variants",
|
|
477
|
+
"id": "components-select-field-select-field--variants",
|
|
478
|
+
"code": "import { MenuItem, SelectField } from '@carto/meridian-ds/components'\nimport { SelectChangeEvent } from '@mui/material'\nimport { useState } from 'react'\n\nconst menuItems = [\n { label: 'Ten: super large text with overflow', id: '10' },\n { label: 'Twenty', id: '20' },\n { label: 'Thirty', id: '30' },\n]\n\nconst SelectFieldItem = ({\n label,\n required,\n placeholder,\n variant,\n helperText,\n size,\n focused,\n disabled,\n error,\n ...rest\n}: SelectFieldProps) => {\n const [content, setContent] = useState([] as string[])\n\n const handleChange = (event: SelectChangeEvent<unknown>) => {\n const value = event.target.value\n setContent(\n // On autofill we get a stringified value\n typeof value === 'string' ? value.split(',') : (value as string[]),\n )\n }\n\n return (\n <SelectField\n {...rest}\n variant={variant}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n value={content}\n focused={focused}\n disabled={disabled}\n onChange={handleChange}\n error={error}\n size={size}\n fullWidth={rest.fullWidth}\n required={required}\n >\n {menuItems.map((o, i) => (\n <MenuItem key={i} value={o.label}>\n {o.label}\n </MenuItem>\n ))}\n </SelectField>\n )\n}\n\nconst Variants = ({\n label,\n placeholder,\n ...rest\n}: SelectFieldProps) => {\n return (\n <Grid container direction='column' spacing={6}>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Filled'}</Label>\n <SelectFieldItem\n {...rest}\n label={label}\n variant='filled'\n placeholder={placeholder}\n />\n </Container>\n </Grid>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Outlined'}</Label>\n <SelectFieldItem\n {...rest}\n label={label}\n variant='outlined'\n placeholder={placeholder}\n />\n </Container>\n </Grid>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Standard'}</Label>\n <SelectFieldItem\n {...rest}\n label={label}\n variant='standard'\n placeholder={placeholder}\n />\n </Container>\n </Grid>\n </Grid>\n )\n}"
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
"name": "LabelAndHelperText",
|
|
482
|
+
"id": "components-select-field-select-field--label-and-helper-text",
|
|
483
|
+
"code": "import { MenuItem, SelectField } from '@carto/meridian-ds/components'\nimport { SelectChangeEvent } from '@mui/material'\nimport { useState } from 'react'\n\nconst menuItems = [\n { label: 'Ten: super large text with overflow', id: '10' },\n { label: 'Twenty', id: '20' },\n { label: 'Thirty', id: '30' },\n]\n\nconst SelectFieldItem = ({\n label,\n required,\n placeholder,\n variant,\n helperText,\n size,\n focused,\n disabled,\n error,\n ...rest\n}: SelectFieldProps) => {\n const [content, setContent] = useState([] as string[])\n\n const handleChange = (event: SelectChangeEvent<unknown>) => {\n const value = event.target.value\n setContent(\n // On autofill we get a stringified value\n typeof value === 'string' ? value.split(',') : (value as string[]),\n )\n }\n\n return (\n <SelectField\n {...rest}\n variant={variant}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n value={content}\n focused={focused}\n disabled={disabled}\n onChange={handleChange}\n error={error}\n size={size}\n fullWidth={rest.fullWidth}\n required={required}\n >\n {menuItems.map((o, i) => (\n <MenuItem key={i} value={o.label}>\n {o.label}\n </MenuItem>\n ))}\n </SelectField>\n )\n}\n\nconst LabelAndHelperText = ({\n label,\n placeholder,\n helperText,\n ...rest\n}: SelectFieldProps) => {\n return (\n <Grid container direction='column' spacing={6}>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Label + helper text'}</Label>\n <SelectFieldItem\n {...rest}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n />\n </Container>\n </Grid>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Without label + helper text'}</Label>\n <SelectFieldItem {...rest} placeholder={placeholder} />\n </Container>\n </Grid>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Only label'}</Label>\n <SelectFieldItem {...rest} label={label} placeholder={placeholder} />\n </Container>\n </Grid>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Only helper text'}</Label>\n <SelectFieldItem\n {...rest}\n placeholder={placeholder}\n helperText={helperText}\n />\n </Container>\n </Grid>\n </Grid>\n )\n}"
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
"name": "Prefix",
|
|
487
|
+
"id": "components-select-field-select-field--prefix",
|
|
488
|
+
"code": "import { MenuItem, SelectField } from '@carto/meridian-ds/components'\nimport { SelectChangeEvent } from '@mui/material'\nimport { useState } from 'react'\n\nconst menuItems = [\n { label: 'Ten: super large text with overflow', id: '10' },\n { label: 'Twenty', id: '20' },\n { label: 'Thirty', id: '30' },\n]\n\nconst SelectFieldItem = ({\n label,\n required,\n placeholder,\n variant,\n helperText,\n size,\n focused,\n disabled,\n error,\n ...rest\n}: SelectFieldProps) => {\n const [content, setContent] = useState([] as string[])\n\n const handleChange = (event: SelectChangeEvent<unknown>) => {\n const value = event.target.value\n setContent(\n // On autofill we get a stringified value\n typeof value === 'string' ? value.split(',') : (value as string[]),\n )\n }\n\n return (\n <SelectField\n {...rest}\n variant={variant}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n value={content}\n focused={focused}\n disabled={disabled}\n onChange={handleChange}\n error={error}\n size={size}\n fullWidth={rest.fullWidth}\n required={required}\n >\n {menuItems.map((o, i) => (\n <MenuItem key={i} value={o.label}>\n {o.label}\n </MenuItem>\n ))}\n </SelectField>\n )\n}\n\nconst Prefix = ({ label, placeholder, ...rest }: SelectFieldProps) => {\n return (\n <Grid container direction='column' spacing={6}>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Prefix (text)'}</Label>\n <SelectFieldItem\n {...rest}\n label={label}\n placeholder={placeholder}\n startAdornment={\n <InputAdornment position='start'>Kg</InputAdornment>\n }\n />\n </Container>\n </Grid>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Prefix (icon)'}</Label>\n <SelectFieldItem\n {...rest}\n label={label}\n placeholder={placeholder}\n startAdornment={\n <InputAdornment position='start'>\n <MapOutlined />\n </InputAdornment>\n }\n />\n </Container>\n </Grid>\n <Grid item>\n <Container>\n <Label variant='body2'>{'None'}</Label>\n <SelectFieldItem {...rest} label={label} placeholder={placeholder} />\n </Container>\n </Grid>\n </Grid>\n )\n}"
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
"name": "Medium",
|
|
492
|
+
"id": "components-select-field-select-field--medium",
|
|
493
|
+
"code": "import { MenuItem, SelectField, Typography } from '@carto/meridian-ds/components'\nimport { SelectChangeEvent, TextFieldProps } from '@mui/material'\nimport { useState } from 'react'\n\nconst menuItems = [\n { label: 'Ten: super large text with overflow', id: '10' },\n { label: 'Twenty', id: '20' },\n { label: 'Thirty', id: '30' },\n]\n\nconst SelectFieldItem = ({\n label,\n required,\n placeholder,\n variant,\n helperText,\n size,\n focused,\n disabled,\n error,\n ...rest\n}: SelectFieldProps) => {\n const [content, setContent] = useState([] as string[])\n\n const handleChange = (event: SelectChangeEvent<unknown>) => {\n const value = event.target.value\n setContent(\n // On autofill we get a stringified value\n typeof value === 'string' ? value.split(',') : (value as string[]),\n )\n }\n\n return (\n <SelectField\n {...rest}\n variant={variant}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n value={content}\n focused={focused}\n disabled={disabled}\n onChange={handleChange}\n error={error}\n size={size}\n fullWidth={rest.fullWidth}\n required={required}\n >\n {menuItems.map((o, i) => (\n <MenuItem key={i} value={o.label}>\n {o.label}\n </MenuItem>\n ))}\n </SelectField>\n )\n}\n\nconst Medium = ({\n label,\n placeholder,\n helperText,\n size,\n ...rest\n}: SelectFieldProps) => {\n const [fixedValue, setFixedValue] = useState('Twenty')\n const [fixedValue2, setFixedValue2] = useState('Twenty')\n const [fixedValue3, setFixedValue3] = useState('Thirty')\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setFixedValue(event.target.value)\n }\n const handleChange2 = (event: React.ChangeEvent<HTMLInputElement>) => {\n setFixedValue2(event.target.value)\n }\n const handleChange3 = (event: React.ChangeEvent<HTMLInputElement>) => {\n setFixedValue3(event.target.value)\n }\n\n return (\n <Grid container spacing={6}>\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Placeholder</Typography>\n <Typography variant='body2'>Custom component</Typography>\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='filled'\n label={label}\n placeholder={placeholder}\n size={size}\n />\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='outlined'\n label={label}\n placeholder={placeholder}\n size={size}\n />\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='standard'\n label={label}\n placeholder={placeholder}\n size={size}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Empty</Typography>\n </Grid>\n <Grid item xs={3}>\n <FormControl>\n <InputLabel>{label}</InputLabel>\n <SelectFieldItem {...rest} variant='filled' size={size} />\n </FormControl>\n </Grid>\n <Grid item xs={3}>\n <FormControl>\n <InputLabel>{label}</InputLabel>\n <SelectFieldItem {...rest} variant='outlined' size={size} />\n </FormControl>\n </Grid>\n <Grid item xs={3}>\n <FormControl>\n <InputLabel>{label}</InputLabel>\n <SelectFieldItem {...rest} variant='standard' size={size} />\n </FormControl>\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Filled</Typography>\n </Grid>\n <Grid item xs={3}>\n <TextField\n {...(rest as TextFieldProps)}\n variant='filled'\n label={label}\n select\n value={fixedValue}\n onChange={handleChange}\n SelectProps={{\n size: size,\n }}\n >\n {menuItems.map((option) => (\n <MenuItem key={option.label} value={option.label}>\n <Typography variant='inherit'>{option.label}</Typography>\n </MenuItem>\n ))}\n </TextField>\n </Grid>\n <Grid item xs={3}>\n <TextField\n {...(rest as TextFieldProps)}\n variant='outlined'\n label={label}\n select\n value={fixedValue2}\n onChange={handleChange2}\n SelectProps={{\n size: size,\n }}\n >\n {menuItems.map((option) => (\n <MenuItem key={option.label} value={option.label}>\n <Typography variant='inherit'>{option.label}</Typography>\n </MenuItem>\n ))}\n </TextField>\n </Grid>\n <Grid item xs={3}>\n <TextField\n {...(rest as TextFieldProps)}\n variant='standard'\n label={label}\n select\n value={fixedValue3}\n onChange={handleChange3}\n SelectProps={{\n size: size,\n }}\n >\n {menuItems.map((option) => (\n <MenuItem key={option.label} value={option.label}>\n <Typography variant='inherit'>{option.label}</Typography>\n </MenuItem>\n ))}\n </TextField>\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Focused</Typography>\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='filled'\n label={label}\n placeholder={placeholder}\n focused\n size={size}\n />\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='outlined'\n label={label}\n placeholder={placeholder}\n focused\n size={size}\n />\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='standard'\n label={label}\n placeholder={placeholder}\n focused\n size={size}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Disabled</Typography>\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='filled'\n label={label}\n placeholder={placeholder}\n disabled\n size={size}\n />\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='outlined'\n label={label}\n placeholder={placeholder}\n disabled\n size={size}\n />\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='standard'\n label={label}\n placeholder={placeholder}\n disabled\n size={size}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Read only</Typography>\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='filled'\n label={label}\n placeholder={placeholder}\n readOnly\n size={size}\n />\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='outlined'\n label={label}\n placeholder={placeholder}\n readOnly\n size={size}\n />\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='standard'\n label={label}\n placeholder={placeholder}\n readOnly\n size={size}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Error</Typography>\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='filled'\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n error\n size={size}\n />\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='outlined'\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n error\n size={size}\n />\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='standard'\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n error\n size={size}\n />\n </Grid>\n </Grid>\n </Grid>\n )\n}"
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
"name": "Small",
|
|
497
|
+
"id": "components-select-field-select-field--small",
|
|
498
|
+
"code": "import { MenuItem, SelectField, Typography } from '@carto/meridian-ds/components'\nimport { SelectChangeEvent, TextFieldProps } from '@mui/material'\nimport { useState } from 'react'\n\nconst menuItems = [\n { label: 'Ten: super large text with overflow', id: '10' },\n { label: 'Twenty', id: '20' },\n { label: 'Thirty', id: '30' },\n]\n\nconst SelectFieldItem = ({\n label,\n required,\n placeholder,\n variant,\n helperText,\n size,\n focused,\n disabled,\n error,\n ...rest\n}: SelectFieldProps) => {\n const [content, setContent] = useState([] as string[])\n\n const handleChange = (event: SelectChangeEvent<unknown>) => {\n const value = event.target.value\n setContent(\n // On autofill we get a stringified value\n typeof value === 'string' ? value.split(',') : (value as string[]),\n )\n }\n\n return (\n <SelectField\n {...rest}\n variant={variant}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n value={content}\n focused={focused}\n disabled={disabled}\n onChange={handleChange}\n error={error}\n size={size}\n fullWidth={rest.fullWidth}\n required={required}\n >\n {menuItems.map((o, i) => (\n <MenuItem key={i} value={o.label}>\n {o.label}\n </MenuItem>\n ))}\n </SelectField>\n )\n}\n\nconst Small = ({\n label,\n placeholder,\n helperText,\n size,\n ...rest\n}: SelectFieldProps) => {\n const [fixedValue, setFixedValue] = useState('Twenty')\n const [fixedValue2, setFixedValue2] = useState('Twenty')\n const [fixedValue3, setFixedValue3] = useState('Thirty')\n const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n setFixedValue(event.target.value)\n }\n const handleChange2 = (event: React.ChangeEvent<HTMLInputElement>) => {\n setFixedValue2(event.target.value)\n }\n const handleChange3 = (event: React.ChangeEvent<HTMLInputElement>) => {\n setFixedValue3(event.target.value)\n }\n\n return (\n <Grid container spacing={6}>\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Placeholder</Typography>\n <Typography variant='body2'>Custom component</Typography>\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='filled'\n label={label}\n placeholder={placeholder}\n size={size}\n />\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='outlined'\n label={label}\n placeholder={placeholder}\n size={size}\n />\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='standard'\n label={label}\n placeholder={placeholder}\n size={size}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Empty</Typography>\n </Grid>\n <Grid item xs={3}>\n <FormControl>\n <InputLabel>{label}</InputLabel>\n <SelectFieldItem {...rest} variant='filled' size={size} />\n </FormControl>\n </Grid>\n <Grid item xs={3}>\n <FormControl>\n <InputLabel>{label}</InputLabel>\n <SelectFieldItem {...rest} variant='outlined' size={size} />\n </FormControl>\n </Grid>\n <Grid item xs={3}>\n <FormControl>\n <InputLabel>{label}</InputLabel>\n <SelectFieldItem {...rest} variant='standard' size={size} />\n </FormControl>\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Filled</Typography>\n </Grid>\n <Grid item xs={3}>\n <TextField\n {...(rest as TextFieldProps)}\n variant='filled'\n label={label}\n select\n value={fixedValue}\n onChange={handleChange}\n SelectProps={{\n size: size,\n }}\n >\n {menuItems.map((option) => (\n <MenuItem key={option.label} value={option.label}>\n <Typography variant='inherit'>{option.label}</Typography>\n </MenuItem>\n ))}\n </TextField>\n </Grid>\n <Grid item xs={3}>\n <TextField\n {...(rest as TextFieldProps)}\n variant='outlined'\n label={label}\n select\n value={fixedValue2}\n onChange={handleChange2}\n SelectProps={{\n size: size,\n }}\n >\n {menuItems.map((option) => (\n <MenuItem key={option.label} value={option.label}>\n <Typography variant='inherit'>{option.label}</Typography>\n </MenuItem>\n ))}\n </TextField>\n </Grid>\n <Grid item xs={3}>\n <TextField\n {...(rest as TextFieldProps)}\n variant='standard'\n label={label}\n select\n value={fixedValue3}\n onChange={handleChange3}\n SelectProps={{\n size: size,\n }}\n >\n {menuItems.map((option) => (\n <MenuItem key={option.label} value={option.label}>\n <Typography variant='inherit'>{option.label}</Typography>\n </MenuItem>\n ))}\n </TextField>\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Focused</Typography>\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='filled'\n label={label}\n placeholder={placeholder}\n focused\n size={size}\n />\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='outlined'\n label={label}\n placeholder={placeholder}\n focused\n size={size}\n />\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='standard'\n label={label}\n placeholder={placeholder}\n focused\n size={size}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Disabled</Typography>\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='filled'\n label={label}\n placeholder={placeholder}\n disabled\n size={size}\n />\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='outlined'\n label={label}\n placeholder={placeholder}\n disabled\n size={size}\n />\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='standard'\n label={label}\n placeholder={placeholder}\n disabled\n size={size}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Read only</Typography>\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='filled'\n label={label}\n placeholder={placeholder}\n readOnly\n size={size}\n />\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='outlined'\n label={label}\n placeholder={placeholder}\n readOnly\n size={size}\n />\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='standard'\n label={label}\n placeholder={placeholder}\n readOnly\n size={size}\n />\n </Grid>\n </Grid>\n\n <Grid item container spacing={2}>\n <Grid item xs={2}>\n <Typography>Error</Typography>\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='filled'\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n error\n size={size}\n />\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='outlined'\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n error\n size={size}\n />\n </Grid>\n <Grid item xs={3}>\n <SelectFieldItem\n {...rest}\n variant='standard'\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n error\n size={size}\n />\n </Grid>\n </Grid>\n </Grid>\n )\n}"
|
|
499
|
+
},
|
|
500
|
+
{
|
|
501
|
+
"name": "Behavior",
|
|
502
|
+
"id": "components-select-field-select-field--behavior",
|
|
503
|
+
"code": "import { MenuItem, SelectField } from '@carto/meridian-ds/components'\nimport { SelectChangeEvent } from '@mui/material'\nimport { useState } from 'react'\n\nconst menuItems = [\n { label: 'Ten: super large text with overflow', id: '10' },\n { label: 'Twenty', id: '20' },\n { label: 'Thirty', id: '30' },\n]\n\nconst SelectFieldItem = ({\n label,\n required,\n placeholder,\n variant,\n helperText,\n size,\n focused,\n disabled,\n error,\n ...rest\n}: SelectFieldProps) => {\n const [content, setContent] = useState([] as string[])\n\n const handleChange = (event: SelectChangeEvent<unknown>) => {\n const value = event.target.value\n setContent(\n // On autofill we get a stringified value\n typeof value === 'string' ? value.split(',') : (value as string[]),\n )\n }\n\n return (\n <SelectField\n {...rest}\n variant={variant}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n value={content}\n focused={focused}\n disabled={disabled}\n onChange={handleChange}\n error={error}\n size={size}\n fullWidth={rest.fullWidth}\n required={required}\n >\n {menuItems.map((o, i) => (\n <MenuItem key={i} value={o.label}>\n {o.label}\n </MenuItem>\n ))}\n </SelectField>\n )\n}\n\nconst Behavior = ({\n label,\n placeholder,\n ...rest\n}: SelectFieldProps) => {\n return (\n <Grid container direction='column' spacing={6}>\n <Grid item>\n <Label variant='subtitle1'>{'Overflow'}</Label>\n <Container style={{ maxWidth: '440px' }}>\n <Label variant='body2'>{'Default'}</Label>\n <SelectFieldItem {...rest} label={label} placeholder={placeholder} />\n </Container>\n </Grid>\n\n <Grid item>\n <Label variant='subtitle1'>{'Grouping'}</Label>\n <Container>\n <Label variant='body2'>{'Pairing'}</Label>\n\n <Grid container spacing={2}>\n <Grid item>\n <SelectFieldItem\n {...rest}\n label={label}\n placeholder={placeholder}\n />\n </Grid>\n <Grid item>\n <SelectFieldItem\n {...rest}\n label={label}\n placeholder={placeholder}\n />\n </Grid>\n </Grid>\n </Container>\n </Grid>\n\n <Grid item>\n <Label variant='subtitle1'>{'Width'}</Label>\n <Container>\n <Label variant='body2'>{'Default (fullWidth)'}</Label>\n <SelectFieldItem {...rest} label={label} placeholder={placeholder} />\n </Container>\n <Container>\n <Label variant='body2'>{'No fullWidth'}</Label>\n <SelectFieldItem\n {...rest}\n label={label}\n placeholder={placeholder}\n fullWidth={false}\n />\n </Container>\n </Grid>\n </Grid>\n )\n}"
|
|
504
|
+
},
|
|
505
|
+
{
|
|
506
|
+
"name": "Grouped",
|
|
507
|
+
"id": "components-select-field-select-field--grouped",
|
|
508
|
+
"code": "import { MenuItem, SelectField, Typography } from '@carto/meridian-ds/components'\nimport { ListItemText, SelectChangeEvent } from '@mui/material'\nimport { useState } from 'react'\n\nconst groupedMenuItems: GroupedItem[] = [\n {\n label: 'The Shawshank Redemption',\n id: '1',\n category: 'Drama',\n secondaryText: '1994 · Frank Darabont',\n },\n {\n label: 'The Godfather',\n id: '2',\n category: 'Drama',\n secondaryText: '1972 · Francis Ford Coppola',\n },\n {\n label: \"Schindler's List\",\n id: '3',\n category: 'Drama',\n secondaryText: '1993 · Steven Spielberg',\n },\n {\n label: 'The Dark Knight',\n id: '4',\n category: 'Action',\n secondaryText: '2008 · Christopher Nolan',\n },\n {\n label: 'Inception',\n id: '5',\n category: 'Action',\n secondaryText: '2010 · Christopher Nolan',\n },\n {\n label: 'The Matrix',\n id: '6',\n category: 'Action',\n secondaryText: '1999 · The Wachowskis',\n },\n {\n label: 'Pulp Fiction',\n id: '7',\n category: 'Crime',\n secondaryText: '1994 · Quentin Tarantino',\n },\n {\n label: 'The Usual Suspects',\n id: '8',\n category: 'Crime',\n secondaryText: '1995 · Bryan Singer',\n },\n]\n\nconst Grouped = ({\n label,\n placeholder,\n helperText,\n size = 'small',\n ...rest\n}: SelectFieldProps) => {\n const [value, setValue] = useState('')\n const [valueExtended, setValueExtended] = useState('')\n\n const handleChange = (event: SelectChangeEvent<unknown>) => {\n setValue(event.target.value as string)\n }\n\n const handleChangeExtended = (event: SelectChangeEvent<unknown>) => {\n setValueExtended(event.target.value as string)\n }\n\n // Group items by category\n const groupedByCategory = groupedMenuItems.reduce<\n Record<string, GroupedItem[]>\n >((acc, item) => {\n const category = item.category\n const categoryItems = acc[category] ?? []\n return {\n ...acc,\n [category]: [...categoryItems, item],\n }\n }, {})\n\n // Render grouped items with MenuItem subtitle for group titles\n const renderGroupedItems = (extended: boolean) => {\n const items: React.ReactNode[] = []\n Object.entries(groupedByCategory).forEach(([category, categoryItems]) => {\n items.push(\n <MenuItem\n key={category}\n subtitle\n component='div'\n tabIndex={-1}\n disabled\n >\n {category}\n </MenuItem>,\n )\n categoryItems.forEach((item) => {\n items.push(\n <MenuItem key={item.id} value={item.id} extended={extended}>\n {extended ? (\n <ListItemText\n primary={item.label}\n secondary={item.secondaryText}\n />\n ) : (\n item.label\n )}\n </MenuItem>,\n )\n })\n })\n return items\n }\n\n return (\n <Grid container direction='column' spacing={6}>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Grouped (default)'}</Label>\n <SelectField\n {...rest}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n value={value}\n onChange={handleChange}\n size={size}\n >\n {renderGroupedItems(false)}\n </SelectField>\n </Container>\n </Grid>\n <Grid item>\n <Container>\n <Label variant='body2'>{'Grouped (extended)'}</Label>\n <SelectField\n {...rest}\n label={label}\n placeholder={placeholder}\n helperText={helperText}\n value={valueExtended}\n onChange={handleChangeExtended}\n size={size}\n displayEmpty\n renderValue={(selected) => {\n if (!selected) {\n return (\n <Typography\n component='span'\n variant={size === 'small' ? 'body2' : 'body1'}\n color='text.hint'\n >\n {placeholder}\n </Typography>\n )\n }\n const item = groupedMenuItems.find((i) => i.id === selected)\n return item?.label\n }}\n >\n {renderGroupedItems(true)}\n </SelectField>\n </Container>\n </Grid>\n <Grid item>\n <DocContainer severity='info'>\n <Typography variant='body2' weight='strong' mb={2}>\n Grouped SelectField\n </Typography>\n <Typography variant='body2' mb={2}>\n Use `MenuItem` with `subtitle` prop to create group headers in\n SelectField. Group headers are non-selectable and visually separate\n option categories.\n </Typography>\n <Typography variant='body2' component='div' mb={2}>\n <DocHighlight component='span'>\n {`<SelectField>\n <MenuItem subtitle component=\"div\" tabIndex={-1} disabled>\n Category Name\n </MenuItem>\n <MenuItem value=\"1\">Option 1</MenuItem>\n <MenuItem value=\"2\">Option 2</MenuItem>\n</SelectField>`}\n </DocHighlight>\n </Typography>\n <Typography variant='body2' weight='strong' mb={1}>\n Key points:\n </Typography>\n <Typography variant='body2' component='div' mb={1}>\n • Use `MenuItem subtitle` with `tabIndex={-1}` and `disabled` for\n group headers\n </Typography>\n <Typography variant='body2' component='div' mb={1}>\n • Add `component="div"` to prevent nesting `li` elements\n </Typography>\n <Typography variant='body2' component='div' mb={1}>\n • For extended height items, add `extended` prop to all MenuItem\n components\n </Typography>\n </DocContainer>\n </Grid>\n </Grid>\n )\n}"
|
|
509
|
+
}
|
|
510
|
+
]
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
"name": "SplitButton",
|
|
514
|
+
"description": "Button paired with a dropdown of related alternative actions. The first option is the default click action; the dropdown exposes the rest. Selecting a dropdown item sets it as the new default and relabels the main button — it does not run the action; only clicking the main button fires `onClick` (pick role, then click to act). Use when there is one primary action plus a small set of close variants (e.g. Save / Save as / Save and close).",
|
|
515
|
+
"curation": {
|
|
516
|
+
"keywords": [
|
|
517
|
+
"button group",
|
|
518
|
+
"menu",
|
|
519
|
+
"picker",
|
|
520
|
+
"chooser",
|
|
521
|
+
"select action",
|
|
522
|
+
"action menu",
|
|
523
|
+
"more actions",
|
|
524
|
+
"export options"
|
|
525
|
+
],
|
|
526
|
+
"decisionTree": [
|
|
527
|
+
{
|
|
528
|
+
"condition": "Selecting a filter value triggered by a button or icon",
|
|
529
|
+
"use": "FilterDropdown",
|
|
530
|
+
"aiHint": "Triggered by a button/icon, single option selection"
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
"condition": "Selecting a sort or setting value in a form",
|
|
534
|
+
"use": "SelectField",
|
|
535
|
+
"aiHint": "Not an action trigger, just selecting a value"
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
"condition": "Collection of unrelated actions",
|
|
539
|
+
"use": "Menu",
|
|
540
|
+
"aiHint": "Use separate Button instances if there are only a few unrelated actions"
|
|
541
|
+
},
|
|
542
|
+
{
|
|
543
|
+
"condition": "More than ~5 related action options",
|
|
544
|
+
"use": "Menu",
|
|
545
|
+
"aiHint": "Switch to SelectField if the goal is choosing a value rather than triggering an action"
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
"condition": "Single action with no variants",
|
|
549
|
+
"use": "Button"
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
"condition": "Dropdown of navigation links or unrelated actions",
|
|
553
|
+
"use": "Menu",
|
|
554
|
+
"aiHint": "SplitButton is for a primary action plus close variants; use Menu when the entries are unrelated or navigational."
|
|
555
|
+
}
|
|
556
|
+
],
|
|
557
|
+
"limitations": [
|
|
558
|
+
"No leading or trailing icon — unlike Button there is no `startIcon`/`endIcon`. If you need an icon on the main action, this is a downgrade from Button."
|
|
559
|
+
]
|
|
560
|
+
},
|
|
561
|
+
"examples": [
|
|
562
|
+
{
|
|
563
|
+
"name": "Playground",
|
|
564
|
+
"id": "components-buttons-splitbutton--playground",
|
|
565
|
+
"code": "import { SplitButton, SplitButtonProps } from '@carto/meridian-ds/components'\n\nconst DEFAULT_OPTIONS = [\n { label: 'Item 1', disabled: false },\n { label: 'Item 2', disabled: false },\n { label: 'Item 3', disabled: true },\n]\n\nconst Playground = ({ size, variant, ...rest }: SplitButtonProps) => (\n <div style={{ minHeight: 200 }}>\n <SplitButton\n {...rest}\n size={size}\n variant={variant}\n options={DEFAULT_OPTIONS}\n onClick={(option) => {\n console.log('Clicked option:', option)\n }}\n />\n </div>\n)"
|
|
566
|
+
},
|
|
567
|
+
{
|
|
568
|
+
"name": "Variants",
|
|
569
|
+
"id": "components-buttons-splitbutton--variants",
|
|
570
|
+
"code": "import { SplitButton, SplitButtonProps, Typography } from '@carto/meridian-ds/components'\n\nconst SPLIT_BUTTON_VARIANTS = ['contained', 'outlined', 'text'] as const\n\nconst DEFAULT_OPTIONS = [\n { label: 'Item 1', disabled: false },\n { label: 'Item 2', disabled: false },\n { label: 'Item 3', disabled: true },\n]\n\nconst VariantTemplate = ({ variant, ...rest }: SplitButtonProps) => {\n return (\n <div style={{ minHeight: 200 }}>\n <SplitButton\n {...rest}\n variant={variant}\n defaultOpen\n options={DEFAULT_OPTIONS}\n />\n </div>\n )\n}\n\nconst Variants = (props: SplitButtonProps) => (\n <Grid container direction='row' spacing={4}>\n {SPLIT_BUTTON_VARIANTS.map((variant) => (\n <Grid item key={variant}>\n <Typography\n variant='subtitle2'\n sx={{ mb: 1, textTransform: 'capitalize' }}\n >\n {variant}\n </Typography>\n <VariantTemplate {...props} variant={variant} />\n </Grid>\n ))}\n </Grid>\n)"
|
|
571
|
+
},
|
|
572
|
+
{
|
|
573
|
+
"name": "States",
|
|
574
|
+
"id": "components-buttons-splitbutton--states",
|
|
575
|
+
"code": "import { SplitButton, SplitButtonProps, Typography } from '@carto/meridian-ds/components'\n\nconst DEFAULT_OPTIONS = [\n { label: 'Item 1', disabled: false },\n { label: 'Item 2', disabled: false },\n { label: 'Item 3', disabled: true },\n]\n\nconst SPLIT_BUTTON_STATES = [\n { label: 'Default', args: {} },\n { label: 'Loading', args: { loading: true } },\n { label: 'Disabled', args: { disabled: true } },\n]\n\nconst States = (props: SplitButtonProps) => (\n <Grid container direction='row' spacing={4}>\n {SPLIT_BUTTON_STATES.map(({ label, args }) => (\n <Grid item key={label}>\n <Typography variant='subtitle2' sx={{ mb: 1 }}>\n {label}\n </Typography>\n <div style={{ minHeight: 200 }}>\n <SplitButton {...props} {...args} options={DEFAULT_OPTIONS} />\n </div>\n </Grid>\n ))}\n </Grid>\n)"
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
"name": "Colors",
|
|
579
|
+
"id": "components-buttons-splitbutton--colors",
|
|
580
|
+
"code": "import { SplitButton, SplitButtonProps, Typography } from '@carto/meridian-ds/components'\n\nconst SPLIT_BUTTON_COLORS = [\n 'default',\n 'primary',\n 'secondary',\n 'error',\n] as const\n\nconst DEFAULT_OPTIONS = [\n { label: 'Item 1', disabled: false },\n { label: 'Item 2', disabled: false },\n { label: 'Item 3', disabled: true },\n]\n\nconst ColorTemplate = ({ color, ...rest }: SplitButtonProps) => {\n return (\n <div style={{ minHeight: 200 }}>\n <SplitButton\n {...rest}\n color={color}\n defaultOpen\n options={DEFAULT_OPTIONS}\n />\n </div>\n )\n}\n\nconst Colors = (props: SplitButtonProps) => (\n <Grid container direction='row' spacing={4}>\n {SPLIT_BUTTON_COLORS.map((color) => (\n <Grid item key={color}>\n <Typography\n variant='subtitle2'\n sx={{ mb: 1, textTransform: 'capitalize' }}\n >\n {color}\n </Typography>\n <ColorTemplate {...props} color={color} />\n </Grid>\n ))}\n </Grid>\n)"
|
|
581
|
+
}
|
|
582
|
+
]
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
"name": "Tag",
|
|
586
|
+
"description": "Compact, display-only label for surfacing a status, category, or short value. Supports semantic color variants, an optional leading icon, filled or outlined styles, and a monospaced `code` type for identifiers or snippets. Non-interactive by design — it has no click, selection, or remove behavior.",
|
|
587
|
+
"curation": {
|
|
588
|
+
"keywords": [
|
|
589
|
+
"chip",
|
|
590
|
+
"badge",
|
|
591
|
+
"pill",
|
|
592
|
+
"token"
|
|
593
|
+
],
|
|
594
|
+
"decisionTree": [
|
|
595
|
+
{
|
|
596
|
+
"condition": "Multiple chips, or chips that are clickable or removable (delete icon)",
|
|
597
|
+
"use": "ChipGroup",
|
|
598
|
+
"aiHint": "ChipGroup wraps MUI Chip with onClick/onDelete handlers and \"+N\" overflow management; Tag is display-only."
|
|
599
|
+
},
|
|
600
|
+
{
|
|
601
|
+
"condition": "Small count or dot indicator anchored to another element (e.g. a notification count on an icon)",
|
|
602
|
+
"use": "Badge",
|
|
603
|
+
"isMUI": true
|
|
604
|
+
}
|
|
605
|
+
],
|
|
606
|
+
"limitations": [
|
|
607
|
+
"Display-only — no onClick, selection, or other interactive behavior.",
|
|
608
|
+
"Not removable — no onDelete or dismiss icon.",
|
|
609
|
+
"No size prop — single fixed compact height."
|
|
610
|
+
]
|
|
611
|
+
},
|
|
612
|
+
"examples": [
|
|
613
|
+
{
|
|
614
|
+
"name": "Playground",
|
|
615
|
+
"id": "components-tag--playground",
|
|
616
|
+
"code": "import { Tag, TagProps } from '@carto/meridian-ds/components'\n\nconst Playground = ({ ...args }: TagProps) => {\n return <Tag {...args} />\n}"
|
|
617
|
+
},
|
|
618
|
+
{
|
|
619
|
+
"name": "Variants",
|
|
620
|
+
"id": "components-tag--variants",
|
|
621
|
+
"code": "import { Tag, TagProps } from '@carto/meridian-ds/components'\n\nconst Variants = ({ color, ...args }: TagProps) => {\n return (\n <Grid container spacing={2}>\n <Grid item>\n <Tag {...args} color={color} variant='filled' label='Filled tag' />\n </Grid>\n <Grid item>\n <Tag {...args} color={color} variant='outlined' label='Outlined tag' />\n </Grid>\n </Grid>\n )\n}"
|
|
622
|
+
},
|
|
623
|
+
{
|
|
624
|
+
"name": "Types",
|
|
625
|
+
"id": "components-tag--types",
|
|
626
|
+
"code": "import { Tag, TagProps } from '@carto/meridian-ds/components'\n\nconst Types = ({ ...args }: TagProps) => {\n return (\n <Grid container spacing={2}>\n <Grid item xs={6}>\n <Grid container spacing={2} direction='column'>\n <Grid item>\n <Tag\n {...args}\n type='default'\n variant='filled'\n label='Inter Font - filled'\n />\n </Grid>\n <Grid item>\n <Tag\n {...args}\n type='code'\n variant='filled'\n label='Overpass Mono - filled'\n />\n </Grid>\n </Grid>\n </Grid>\n <Grid item xs={6}>\n <Grid container spacing={2} direction='column'>\n <Grid item>\n <Tag\n {...args}\n type='default'\n variant='outlined'\n label='Inter Font - outlined'\n />\n </Grid>\n <Grid item>\n <Tag\n {...args}\n type='code'\n variant='outlined'\n label='Overpass Mono - outlined'\n />\n </Grid>\n </Grid>\n </Grid>\n </Grid>\n )\n}"
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
"name": "Colors",
|
|
630
|
+
"id": "components-tag--colors",
|
|
631
|
+
"code": "import { Tag, TagProps } from '@carto/meridian-ds/components'\nimport React from 'react'\n\nconst colorsOptions = [\n { color: 'default' },\n { color: 'neutral' },\n { color: 'primary' },\n { color: 'secondary' },\n { color: 'success' },\n { color: 'warning' },\n { color: 'error' },\n] as const\n\nconst Colors = ({ ...args }: TagProps) => {\n return (\n <Grid container spacing={2}>\n <Grid item xs={6}>\n <Grid container spacing={2} direction='column'>\n {colorsOptions.map((colorOption, index) => (\n <React.Fragment key={index}>\n <Grid item>\n <Tag\n {...args}\n {...colorOption}\n variant='filled'\n label={`${colorOption.color} - filled`}\n />\n </Grid>\n <Grid item mb={3}>\n <Tag\n {...args}\n {...colorOption}\n variant='filled'\n label={`${colorOption.color} - filled disabled`}\n disabled\n />\n </Grid>\n </React.Fragment>\n ))}\n </Grid>\n </Grid>\n <Grid item xs={6}>\n <Grid container spacing={2} direction='column'>\n {colorsOptions.map((colorOption, index) => (\n <React.Fragment key={index}>\n <Grid item>\n <Tag\n {...args}\n {...colorOption}\n variant='outlined'\n label={`${colorOption.color} - outlined`}\n />\n </Grid>\n <Grid item mb={3}>\n <Tag\n {...args}\n {...colorOption}\n variant='outlined'\n label={`${colorOption.color} - outlined disabled`}\n disabled\n />\n </Grid>\n </React.Fragment>\n ))}\n </Grid>\n </Grid>\n </Grid>\n )\n}"
|
|
632
|
+
},
|
|
633
|
+
{
|
|
634
|
+
"name": "CustomColor",
|
|
635
|
+
"id": "components-tag--custom-color",
|
|
636
|
+
"code": "import { Tag, TagProps } from '@carto/meridian-ds/components'\n\nconst CustomColor = ({ ...args }: TagProps) => {\n return <Tag {...args} />\n}"
|
|
637
|
+
},
|
|
638
|
+
{
|
|
639
|
+
"name": "WithIcons",
|
|
640
|
+
"id": "components-tag--with-icons",
|
|
641
|
+
"code": "import { Tag, TagProps } from '@carto/meridian-ds/components'\nimport { AddCircleOutlineOutlined, ChangeCircleOutlined, CloseOutlined, DangerousOutlined, DoneOutlined } from '@mui/icons-material'\n\nconst WithIcons = ({ ...args }: TagProps) => {\n const icons = [\n { icon: <CloseOutlined />, color: 'default' },\n { icon: <CloseOutlined />, color: 'neutral' },\n { icon: <DoneOutlined />, color: 'primary' },\n { icon: <AddCircleOutlineOutlined />, color: 'secondary' },\n { icon: <CheckCircleOutlined />, color: 'success' },\n { icon: <DangerousOutlined />, color: 'error' },\n { icon: <ChangeCircleOutlined />, color: 'warning' },\n ] as const\n\n return (\n <Grid container spacing={2}>\n <Grid item xs={3}>\n <Grid container spacing={2} direction='column'>\n {icons.map(({ icon, color }, index) => (\n <Grid item key={index}>\n <Tag\n {...args}\n color={color}\n variant='filled'\n icon={icon}\n label={`${color} - filled`}\n />\n </Grid>\n ))}\n <Grid item>\n <Tag\n {...args}\n color='primary'\n variant='filled'\n icon={<DoneOutlined />}\n label='Disabled - filled'\n disabled\n />\n </Grid>\n </Grid>\n </Grid>\n <Grid item xs={3}>\n <Grid container spacing={2} direction='column'>\n {icons.map(({ icon, color }, index) => (\n <Grid item key={index}>\n <Tag\n {...args}\n color={color}\n variant='outlined'\n icon={icon}\n label={`${color} - outlined`}\n />\n </Grid>\n ))}\n <Grid item>\n <Tag\n {...args}\n color='primary'\n variant='outlined'\n icon={<DoneOutlined />}\n label='Disabled - outlined'\n disabled\n />\n </Grid>\n </Grid>\n </Grid>\n <Grid item xs={3}>\n <Grid container spacing={2} direction='column'>\n {icons.map(({ icon, color }, index) => (\n <Grid item key={index}>\n <Tag\n {...args}\n color={color}\n variant='filled'\n type='code'\n icon={icon}\n label={`${color} - code filled`}\n />\n </Grid>\n ))}\n <Grid item>\n <Tag\n {...args}\n color='primary'\n variant='filled'\n type='code'\n icon={<DoneOutlined />}\n label='Disabled - filled'\n disabled\n />\n </Grid>\n </Grid>\n </Grid>\n <Grid item xs={3}>\n <Grid container spacing={2} direction='column'>\n {icons.map(({ icon, color }, index) => (\n <Grid item key={index}>\n <Tag\n {...args}\n color={color}\n variant='outlined'\n type='code'\n icon={icon}\n label={`${color} - code outlined`}\n />\n </Grid>\n ))}\n <Grid item>\n <Tag\n {...args}\n color='primary'\n variant='outlined'\n type='code'\n icon={<DoneOutlined />}\n label='Disabled - outlined'\n disabled\n />\n </Grid>\n </Grid>\n </Grid>\n </Grid>\n )\n}"
|
|
642
|
+
}
|
|
643
|
+
]
|
|
644
|
+
},
|
|
645
|
+
{
|
|
646
|
+
"name": "Typography",
|
|
647
|
+
"description": "Themed text element for headings, body copy, captions, and labels. Adds semantic font weight (regular, medium, strong) and italic style support on top of the standard typographic variants.",
|
|
648
|
+
"curation": {
|
|
649
|
+
"keywords": [
|
|
650
|
+
"heading",
|
|
651
|
+
"paragraph",
|
|
652
|
+
"title",
|
|
653
|
+
"label"
|
|
654
|
+
],
|
|
655
|
+
"mui": [
|
|
656
|
+
{
|
|
657
|
+
"name": "variant",
|
|
658
|
+
"aiHint": "When using heading variants (h1-h6), don't skip levels (h1 -> h3 without h2). To control visual size independently of the rendered tag, set variant for styling and pass component to override the HTML element."
|
|
659
|
+
},
|
|
660
|
+
"color",
|
|
661
|
+
"align",
|
|
662
|
+
{
|
|
663
|
+
"name": "component",
|
|
664
|
+
"aiHint": "Use to render a different element, e.g., component='p' for a paragraph within another Typography."
|
|
665
|
+
},
|
|
666
|
+
{
|
|
667
|
+
"name": "noWrap",
|
|
668
|
+
"aiHint": "Truncates with ellipsis only when the parent has a constrained width. In flex/grid containers, also set minWidth=0 on the parent or the text won't actually truncate."
|
|
669
|
+
},
|
|
670
|
+
"gutterBottom"
|
|
671
|
+
],
|
|
672
|
+
"decisionTree": [
|
|
673
|
+
{
|
|
674
|
+
"condition": "Clickable text that navigates to a URL",
|
|
675
|
+
"use": "Link"
|
|
676
|
+
},
|
|
677
|
+
{
|
|
678
|
+
"condition": "Editable text inside a form input",
|
|
679
|
+
"use": "TextField",
|
|
680
|
+
"isMUI": true
|
|
681
|
+
},
|
|
682
|
+
{
|
|
683
|
+
"condition": "Text label on a button",
|
|
684
|
+
"use": "Button",
|
|
685
|
+
"aiHint": "Pass the label as Button children rather than nesting Typography"
|
|
686
|
+
}
|
|
687
|
+
]
|
|
688
|
+
},
|
|
689
|
+
"examples": [
|
|
690
|
+
{
|
|
691
|
+
"name": "Playground",
|
|
692
|
+
"id": "components-typography--playground",
|
|
693
|
+
"code": "import { Typography, TypographyProps } from '@carto/meridian-ds/components'\n\nconst Playground = (props: TypographyProps) => <Typography {...props} />"
|
|
694
|
+
},
|
|
695
|
+
{
|
|
696
|
+
"name": "NoWrap",
|
|
697
|
+
"id": "components-typography--no-wrap",
|
|
698
|
+
"code": "import { Typography, TypographyProps } from '@carto/meridian-ds/components'\n\nconst NoWrap = (props: TypographyProps) => <Typography {...props} />"
|
|
699
|
+
},
|
|
700
|
+
{
|
|
701
|
+
"name": "Italic",
|
|
702
|
+
"id": "components-typography--italic",
|
|
703
|
+
"code": "import { Typography, TypographyProps } from '@carto/meridian-ds/components'\n\nconst Italic = (props: TypographyProps) => <Typography {...props} />"
|
|
704
|
+
},
|
|
705
|
+
{
|
|
706
|
+
"name": "Weight",
|
|
707
|
+
"id": "components-typography--weight",
|
|
708
|
+
"code": "import { Typography } from '@carto/meridian-ds/components'\n\nconst Weight = () => (\n <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>\n <Typography weight='regular' variant='body1'>\n Regular weight text\n </Typography>\n <Typography weight='medium' variant='body1'>\n Medium weight text\n </Typography>\n <Typography weight='strong' variant='body1'>\n Strong weight text\n </Typography>\n </div>\n )"
|
|
709
|
+
},
|
|
710
|
+
{
|
|
711
|
+
"name": "Variant",
|
|
712
|
+
"id": "components-typography--variant",
|
|
713
|
+
"code": "import { Link, Typography } from '@carto/meridian-ds/components'\n\nconst Variant = () => (\n <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>\n <DocContainer>\n See tokens section for more information about the typography variants:{' '}\n <Link href='/?path=/docs/foundations-typography-tokens--docs'>\n Typography Tokens\n </Link>\n </DocContainer>\n <Typography variant='h1'>H1 Headline</Typography>\n <Typography variant='h2'>H2 Headline</Typography>\n <Typography variant='h3'>H3 Headline</Typography>\n <Typography variant='h4'>H4 Headline</Typography>\n <Typography variant='h5'>H5 Headline</Typography>\n <Typography variant='h6'>H6 Headline</Typography>\n <Typography variant='subtitle1'>Subtitle 1</Typography>\n <Typography variant='subtitle2'>Subtitle 2</Typography>\n <Typography variant='body1'>Body 1</Typography>\n <Typography variant='body2'>Body 2</Typography>\n <Typography variant='button'>Button</Typography>\n <Typography variant='caption'>Caption</Typography>\n <Typography variant='overline'>Overline</Typography>\n <Typography variant='overlineDelicate'>Overline Delicate</Typography>\n <Typography variant='code1'>Code 1</Typography>\n <Typography variant='code2'>Code 2</Typography>\n <Typography variant='code3'>Code 3</Typography>\n </div>\n )"
|
|
714
|
+
},
|
|
715
|
+
{
|
|
716
|
+
"name": "Color",
|
|
717
|
+
"id": "components-typography--color",
|
|
718
|
+
"code": "import { Typography } from '@carto/meridian-ds/components'\n\nconst Color = () => (\n <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>\n <Typography variant='body1' color='primary.dark'>\n Primary dark color\n </Typography>\n <Typography variant='body1' color='brand.navyBlue'>\n Brand navy blue color\n </Typography>\n <Typography variant='body1' color='error.main'>\n Error color\n </Typography>\n <Typography variant='body1' color='warning.main'>\n Warning color\n </Typography>\n <Typography variant='body1' color='success.main'>\n Success color\n </Typography>\n <Typography variant='body1' color='default.main'>\n Default color\n </Typography>\n </div>\n )"
|
|
719
|
+
}
|
|
720
|
+
]
|
|
721
|
+
}
|
|
722
|
+
]
|
|
723
|
+
}
|