I'm trying to set custom labels for my controls in Storybook as outlined in the instructions here, but it's not working as expected. According to the instructions you can specify control.labels to configure custom labels for your checkbox, radio, or select input.
Right now I have a prop of size that allows the user to select the size of the component, but in Storybook it's showing the number value as opposed to name. e.g.
Instead of the number values I want the labels to read the names from the enum below.
export enum sizes {
small = 32,
default = 50,
large = 100,
};
How can I update Storybook to use the enum sizes name instead of the value?
// storybook
export default {
title: 'Components/Spinner',
component: Spinner,
controls: { expanded: true },
argTypes: {
type: {
options: ['primary', 'secondary', 'success', 'warning', 'danger', 'info', 'light'],
control: { type: 'radio'},
},
size: {
options: [sizes.default, sizes.small, sizes.large],
control: {
type: 'radio',
labels: {
Default: 'Default',
Small: 'Small',
Large: 'Large'
},
},
}
}
} as Meta;
FYI: If I update options to the following:
options: sizes,
I get both the name and the value and only the name works
In case anyone else comes across this issue I solved it by manually typing in the values. According to this Stackoverflow post enums end up as object. So it was outputting both the key and values.
export default {
title: 'Components/Spinner',
component: Spinner,
controls: { expanded: true },
argTypes: {
type: {
options: ['primary', 'secondary', 'success', 'warning', 'danger', 'info', 'light'],
control: { type: 'radio'},
},
size: {
options: [32, 50, 100],
control: {
type: 'radio',
labels: {
32: 'small',
50: 'default',
100: 'large',
},
},
}
}
} as Meta;
Related
I'm in the process of creating an internal component library using Storybook and Kendo React and I'm having to explicitly define argTypes for controls for every prop in order to get them to give me anything but a string input (with the sole exception of booleans).
Here's a sample of one of my stories:
import React from "react";
import { ComponentStory, ComponentMeta } from "#storybook/react";
import { TestAvatar } from "../../components/Avatar/TestAvatar";
export default {
title: "Atomic Components/Test Avatar",
component: TestAvatar,
} as ComponentMeta<typeof TestAvatar>;
const Template: ComponentStory<typeof TestAvatar> = ({ ...args }: any) => (
<TestAvatar {...args} />
);
export const Standard = Template.bind({});
Standard.args = {
border: false,
themeColor: "base",
fillMode: "solid",
rounded: "medium",
size: "medium",
type: undefined,
};
Standard.argTypes = {
themeColor: {
options: ["base", "primary", "secondary", "tertiary", "success", "error"],
control: { type: "select" },
},
rounded: {
options: ["small", "medium", "large", "full", null],
control: { type: "select" },
},
size: {
options: ["small", "medium", "large"],
control: { type: "select" },
},
fillMode: {
options: ["solid", "outline"],
control: { type: "radio" },
},
type: {
options: ["image", "text", "icon"],
control: { type: "select" },
},
};
I have all the standard addons, although I haven't created any typescript options in main.js - I've tried, using info I got from this question but they don't seem to make any difference.
I've tried a few things, using Story and Meta from Storybook instead of the newer ComponentStory and ComponentMeta, I've tried extending the AvatarProps interface and I have also tried using the Kendo AvatarProps interface directly, but I can't find a way around it.
I suspect it's to do with how the Kendo library is typed.
I want to have to avoid creating controls for every single component I'm creating - does anyone have any ideas on how I can circumvent that amount of unnecessary work?
I have a simple antd bar chart within my React app. First it gets displayed fine, but when the user interacts with the website (and changes the global state) sometimes all of a sudden the chart shrinks.
I tried memoizing the chart and wrapped the component with memo() so that no state change in a parent component affects the chart but that did not help either.
As you can see the canvas has the correct dimensions but the chart drawn on that canvas is not filling it up anymore. The chart should be as big as the lightblue box:
import { memo } from 'react';
import { Column } from '#ant-design/plots';
import theme from '#themes/antd.charts.json';
const Chart = memo(({ data, type }) => {
const chartConfig = {
data,
loading: data.length === 0,
theme,
xField: 'type',
yField: 'value',
seriesField: 'type',
yAxis: {
label: {
formatter: (v) => numeral(v).format('0,0'),
},
},
xAxis: false,
height: 300,
appendPadding: 16,
legend: {
position: 'bottom',
flipPage: false,
itemWidth: 580 / 5, //todo: make dynamic depending on width/count
},
interactions: [
{
type: 'element-active',
},
],
label: {
position: 'top',
offsetY: 8,
formatter: ({ value }) =>
`${numeral(value).format('0,0')} ${type === 'hectare' ? `ha` : ``}`,
},
};
return <Column {...chartConfig} />;
});
I am having an issue were I need to generate a form from a schema and have fields dependent on each other such as enabled/disable show/hide etc.
my schema looks something like this.
contractorInformation: {
title: "ContractorInformation",
type: "object",
properties: {
contractorName: {
title: "Contractor Name",
type: "string",
ui: "input",
constraints: {
required: true
}
},
contractorFavouriteAnimal: {
title: "Contractor Favourite Animal",
type: "string",
ui: "input",
constraints: {},
dependencies: {
disabled: true,
watching: "contractorName"
// //disabled={!fullName || fullName.length === 0 || errors.fullName}
}
},
contractorEmail: {
title: "Contractor Email",
type: "string",
ui: "input",
constraints: {
common: 10
}
}
}
},
agencyInformation: {
title: "ContractorInformation",
type: "object",
properties: {
contractorName: {
title: "Contractor Name",
type: "string",
ui: "input",
constraints: {
required: true,
minLength: 3,
maxLength: 5
},
dependencies: {
disabled: true,
watching: "agencyName"
}
}
}
}
}
const watchThese = watch()
would allow me to watch everything but if I wanted to change this field from disabled to enabled I could use
<input disabled={!watchThese || watchThese.length === 0 || watchThese.fullName}/>
which works but is obviously triggered by every field.
How could I generate a dynamic watch()/useWatch() from a schema and be able to access the specific dependencies I need to enable/disable the input.
Any help would be gratefully received.
For future reference I solved it by using
export const FormField = () =>
{Object.entries(schema?.actions ?? {}).forEach(([key, value]) => value(watch(key)));
return (<div></div>)}
and update schema to match.
I have an angularjs application with the library Highcharts.
In my application I have some graphs and want to export the data of the graphs in a CSV file. So I used the exporting function from highcharts but I have a problem with the dates. On my graphs, I display the dates with a format "MM/DD/YYYY hh:mm:ss" so when I export my data, I have the same format but I would have the dates in milliseconds. I try to change teh 'dateFormat' field in the exporting options but milliseconds is not part of the accepted formats.
This is my graph options:
widgetCtrl.chartDataLine = {
chart: {
type: 'spline',
zoomType: 'x',
isZoomed: false,
marginTop:55
},
title: {
text: 'title',
align:'left',
x: 20,
y: 18,
style: {
fontSize: '14px'
}
},
xAxis: {
type: 'datetime',
title: {
text: 'Date time'
}
},
yAxis: {
title: {
text: 'Power (W)'
}
},
boost: {
enabled: true
},
exporting: {
fallbackToExportServer: false,
enabled: true,
allowHTML: true,
filename: 'myFile',
menuItemDefinitions: {
downloadJSON: {
onclick: function () {
downloadJSON('myFile.JSON', widgetCtrl.chartDataLine.series);
},
text: 'Download JSON'
}
},
csv: {
decimalPoint: '.',
dateFormat: '%Y-%m-%d %H:%M:%S'
},
buttons: {
contextButton: {
menuItems: [
'printChart',
'downloadPNG',
'downloadJPEG',
'downloadPDF',
'downloadSVG',
'downloadCSV',
'downloadJSON'
]
}
}
},
navigation: {
buttonOptions: {
align: 'left'
}
}
series: [...]
};
Do you have an idea how I coul do that without writing myself teh csv file but using the highcharts functions ?
Unfortunately, Highcharts does not have the default option to export data in milliseconds (timestamp). However, it can be done easily by wrapping Highcharts.Chart.prototype.getDataRows method and map the data array which is used for export.
(function(H) {
H.wrap(H.Chart.prototype, 'getDataRows', function(proceed, multiLevelHeaders) {
var rows = proceed.call(this, multiLevelHeaders);
rows = rows.map(row => {
if (row.x) {
row[0] = row.x;
}
return row;
});
return rows;
});
}(Highcharts));
Demo:
https://jsfiddle.net/BlackLabel/5p1nvq37/
I am using react-jsonschema-form to create a form. Single components are displaying fine but array components are coming in a row. How Can I make them appear one array object in a row so that everytime I click Add button , new array object is rendered in new row. Code is as follows:
const schema = {
type: "object",
properties: {
Name: { type: "string", title: "Name", default: "A new Task" },
Title: { type: "object", properties: { First: { type: "string" }, Second: { type: "string" } } },
XYZ: { type: "array", items: { type: "object", properties: { Third: { type: "string" }, Forth: { type: "boolean", enum: [true, false], enumNames: ["True", "False"] } } } }
}
}
const uiSchema = {
"ui:order": ["Name", "Title", "Done"],
Name: { "ui:widget": "textarea" },
Title: { First: { "ui:widget": "textarea" }, Second: { "ui:widget": "textarea" } },
XYZ: { items: { Third: { "ui:widget": "textarea" }, Forth: { "ui:widget": "radio", "ui:options": { inline: true } } }, "ui:options": { orderable: false, removable: true, inline: false } }
}
Form Code is as Follows:
<Form schema={schema}
// formData = {defaultData}
uiSchema={uiSchema}
onChange={log("changed")}
onSubmit={SubmitRoutine}
onError={ErrorRoutine}
/>
As shown in the following picture Array XYZ objects are fixed width and displaying next to each other. I want them full width and every object in new row. I am using React and Bootstrap4
Also very time I have to even add first object by clicking Plus button. I want first object to appear itself. Please let me know how may I fix it. Thanks
Checkout this library. It allows laying out your form using bootstrap-grid.
It could be achieved with pure CSS, provided there is no need to reflect order in the model:
/* class of a wrapping element */
.array-item-list {
display: flex;
/* column, column-reverse, row, row-reverse */
flex-direction: column-reverse;
}