mirror of https://github.com/rancher/dashboard.git
Initial storybook support
This commit is contained in:
parent
e4b9c1e18c
commit
f081a365a6
|
|
@ -91,6 +91,9 @@ sw.*
|
||||||
# Mac OSX
|
# Mac OSX
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
# Cypress e2e testing
|
||||||
cypress/videos
|
cypress/videos
|
||||||
cypress/screenshots
|
cypress/screenshots
|
||||||
|
|
||||||
|
# Storybook
|
||||||
|
storybook-static/
|
||||||
|
|
|
||||||
|
|
@ -1,66 +1,47 @@
|
||||||
const { CreateVolumePermissionModifications, Phase1DHGroupNumbersListValue } = require('@aws-sdk/client-ec2');
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"stories": [
|
"stories": [
|
||||||
|
"../stories/**/Welcome.stories.mdx",
|
||||||
"../stories/**/*.stories.mdx",
|
"../stories/**/*.stories.mdx",
|
||||||
"../stories/**/*.stories.@(js|jsx|ts|tsx)"
|
"../stories/**/*.stories.@(js|jsx|ts|tsx)"
|
||||||
],
|
],
|
||||||
"addons": [
|
"addons": [
|
||||||
"@storybook/addon-links",
|
"@storybook/addon-links",
|
||||||
"@storybook/addon-essentials",
|
"@storybook/addon-essentials",
|
||||||
"@storybook/addon-a11y"
|
"@storybook/addon-a11y",
|
||||||
|
"storybook-dark-mode"
|
||||||
],
|
],
|
||||||
|
|
||||||
webpackFinal: async (config, { configType }) => {
|
webpackFinal: async (config, { configType }) => {
|
||||||
const baseFolder = path.resolve(__dirname, '..');
|
const baseFolder = path.resolve(__dirname, '..');
|
||||||
const assets = path.resolve(__dirname, '..', 'assets');
|
|
||||||
|
|
||||||
const sassLoader = {
|
const sassLoader = {
|
||||||
loader: 'sass-loader',
|
loader: 'sass-loader',
|
||||||
options: {
|
options: {
|
||||||
// prependData: `@import '${assets}/styles/app.scss'; @import '$a`,
|
|
||||||
prependData: `@import '~assets/styles/app.scss'; @import '~stories/global.scss'; `,
|
prependData: `@import '~assets/styles/app.scss'; @import '~stories/global.scss'; `,
|
||||||
sassOptions: {
|
|
||||||
// importer: (url, resourcePath) => {
|
|
||||||
// console.log('>>>>>> ' + url);
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make whatever fine-grained changes you need
|
|
||||||
config.module.rules.push({
|
config.module.rules.push({
|
||||||
test: /\.scss$/,
|
test: /\.scss$/,
|
||||||
use: ['style-loader', 'css-loader', sassLoader],
|
use: ['style-loader', 'css-loader', sassLoader],
|
||||||
include: path.resolve(__dirname, '../'),
|
include: path.resolve(__dirname, '../'),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
config.module.rules.unshift({
|
||||||
|
test: /\.ya?ml$/i,
|
||||||
|
loader: 'js-yaml-loader',
|
||||||
|
options: { name: '[path][name].[ext]' },
|
||||||
|
});
|
||||||
|
|
||||||
// Root path
|
// Root path
|
||||||
config.resolve.alias['~'] = path.dirname(path.resolve(__dirname));
|
config.resolve.alias['~'] = baseFolder;
|
||||||
config.resolve.alias['@'] = path.dirname(path.resolve(__dirname));
|
config.resolve.alias['@'] = baseFolder;
|
||||||
|
|
||||||
// Cheat for importing ~assets
|
// Cheat for importing ~assets
|
||||||
config.resolve.modules.push(baseFolder);
|
config.resolve.modules.push(baseFolder);
|
||||||
|
|
||||||
// console.log(config);
|
|
||||||
|
|
||||||
// config.resolve.roots = [path.dirname(path.resolve(__dirname))];
|
|
||||||
|
|
||||||
// TODO: To fix xterm and a couple of others
|
|
||||||
// config.resolve.plugins.push({
|
|
||||||
// apply: (config, resolver) => {
|
|
||||||
// config.plugin('module', function (init, callback) {
|
|
||||||
// console.log(init);
|
|
||||||
|
|
||||||
// return resolver.doResolve()
|
|
||||||
// callback(null);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// Return the altered config
|
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
<link rel="shortcut icon" href="/storybook.ico">
|
||||||
|
<link rel="icon" type="image/png" href="/storybook.png" sizes="192x192">
|
||||||
|
|
@ -1,27 +1,39 @@
|
||||||
// .storybook/manager.js
|
|
||||||
|
|
||||||
import { addons } from '@storybook/addons';
|
import { addons } from '@storybook/addons';
|
||||||
import rancherTheme from './theme';
|
import rancherTheme from './theme';
|
||||||
|
import installShortcut from './theme-shortcut';
|
||||||
|
|
||||||
addons.setConfig({
|
addons.setConfig({
|
||||||
panelPosition: 'right',
|
panelPosition: 'right',
|
||||||
theme: rancherTheme
|
theme: rancherTheme
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const loader = window.onload;
|
||||||
|
window.onload = () => {
|
||||||
|
const ch = addons.getChannel();
|
||||||
|
ch.on('shortcut-toggle-dark-mode', (a) => {
|
||||||
|
const toolbar = document.getElementsByClassName('os-content');
|
||||||
|
if (toolbar.length > 2) {
|
||||||
|
const aTags = toolbar[1].getElementsByTagName("button");
|
||||||
|
const searchText = "Change theme to ";
|
||||||
|
let found;
|
||||||
|
|
||||||
// let firstLoad = true;
|
for (var i = 0; i < aTags.length; i++) {
|
||||||
// addons.register('my-organisation/my-addon', (storybookAPI) => {
|
if (aTags[i].title && aTags[i].title.indexOf(searchText) === 0) {
|
||||||
// storybookAPI.on(SET_CURRENT_STORY, ((kind, story) => {
|
found = aTags[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// console.log('<<<<<<<<<<<<<<<<<<<<<<<<<');
|
if (found) {
|
||||||
// // when you enter a story, if you are just loading storybook up, default to a specific kind/story.
|
found.click();
|
||||||
// if (firstLoad) {
|
}
|
||||||
// firstLoad = false; // make sure to set this flag to false, otherwise you will never be able to look at another story.
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// console.log('selecting story....');
|
// Add keyboard shortcut to toggle between dark and light modes
|
||||||
// console.log(kind);
|
installShortcut();
|
||||||
// console.log(story);
|
|
||||||
// storybookAPI.selectStory('BadgeState', 'Primary');
|
if (loader) {
|
||||||
// }
|
loader();
|
||||||
// }));
|
}
|
||||||
// });
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,13 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@storybook/addon-actions": "^6.3.7",
|
"@storybook/addon-actions": "^6.3.8",
|
||||||
"@storybook/addon-essentials": "^6.3.7",
|
"@storybook/addon-essentials": "^6.3.8",
|
||||||
"@storybook/addon-links": "^6.3.7",
|
"@storybook/addon-links": "^6.3.8",
|
||||||
"@storybook/addon-a11y": "^6.3.7",
|
"@storybook/addon-a11y": "^6.3.8",
|
||||||
"@storybook/vue": "^6.3.7",
|
"@storybook/vue": "^6.3.8",
|
||||||
|
"storybook-dark-mode": "^1.0.8",
|
||||||
|
"storybook-auto-events": "^0.1.1",
|
||||||
"vue-loader": "^15.9.8"
|
"vue-loader": "^15.9.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,15 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import Vuex from 'vuex';
|
import Vuex from 'vuex';
|
||||||
|
import { themes } from '@storybook/theming';
|
||||||
|
import { get } from '@/utils/object';
|
||||||
|
import IntlMessageFormat from 'intl-messageformat';
|
||||||
|
import installShortcut from './theme-shortcut';
|
||||||
|
import withEvents from 'storybook-auto-events';
|
||||||
|
|
||||||
// const i18n = require('../store/i18n');
|
const i18nStrings = require('../assets/translations/en-us.yaml');
|
||||||
|
|
||||||
// require('../plugins/i18n');
|
// Register custom i18n plugin
|
||||||
|
require('../plugins/i18n');
|
||||||
// console.log(i18n);
|
|
||||||
|
|
||||||
//const store = require('./store');
|
//const store = require('./store');
|
||||||
|
|
||||||
|
|
@ -14,9 +18,14 @@ Vue.use(Vuex);
|
||||||
const store = new Vuex.Store({
|
const store = new Vuex.Store({
|
||||||
getters: {
|
getters: {
|
||||||
'i18n/t': state => (key, args) => {
|
'i18n/t': state => (key, args) => {
|
||||||
console.log('get');
|
const msg = get(i18nStrings, key) || key;
|
||||||
|
|
||||||
return key;
|
if ( msg?.includes('{')) {
|
||||||
|
const formatter = new IntlMessageFormat(msg, state.selected);
|
||||||
|
return formatter.format(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
return msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -33,40 +42,36 @@ Vue.use(storePlugin);
|
||||||
export const parameters = {
|
export const parameters = {
|
||||||
actions: { argTypesRegex: "^on[A-Z].*" },
|
actions: { argTypesRegex: "^on[A-Z].*" },
|
||||||
layout: 'centered',
|
layout: 'centered',
|
||||||
|
// viewMode: 'docs',
|
||||||
|
// Auto set controls based on the property name
|
||||||
controls: {
|
controls: {
|
||||||
matchers: {
|
matchers: {
|
||||||
color: /(background|color)$/i,
|
color: /(background|color)$/i,
|
||||||
date: /Date$/,
|
date: /Date$/,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
darkMode: {
|
||||||
|
dark: {
|
||||||
|
...themes.dark,
|
||||||
|
brandTitle: 'Rancher Storybook',
|
||||||
|
brandImage: 'https://raw.githubusercontent.com/rancher/dashboard/master/assets/images/pl/dark/rancher-logo.svg'
|
||||||
|
},
|
||||||
|
light: {
|
||||||
|
...themes.normal,
|
||||||
|
brandTitle: 'Rancher Storybook',
|
||||||
|
brandImage: 'https://raw.githubusercontent.com/rancher/dashboard/master/assets/images/pl/rancher-logo.svg'
|
||||||
|
},
|
||||||
|
darkClass: 'theme-dark',
|
||||||
|
lightClass: 'theme-light',
|
||||||
|
stylePreview: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// export const globalTypes = {
|
export const decorators = [
|
||||||
// language: {
|
withEvents
|
||||||
// name: "i18n",
|
];
|
||||||
// description: "i18n selector",
|
|
||||||
// defaultValue: "en",
|
|
||||||
// toolbar: {
|
|
||||||
// items: ["en", "fr"],
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// lightTheme: {
|
|
||||||
// name: "Light",
|
|
||||||
// description: "theme selector",
|
|
||||||
// defaultValue: "light",
|
|
||||||
// toolbar: {
|
|
||||||
// showName: true,
|
|
||||||
// items: []
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// darkTheme: {
|
|
||||||
// name: "Dark",
|
|
||||||
// description: "theme selector",
|
|
||||||
// defaultValue: "dark",
|
|
||||||
// toolbar: {
|
|
||||||
// showName: true,
|
|
||||||
// items: []
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// };
|
|
||||||
|
|
||||||
|
// Add keyboard shortcut to toggle between dark and light modes
|
||||||
|
window.onload = () => {
|
||||||
|
installShortcut();
|
||||||
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 759 B |
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { addons } from '@storybook/addons';
|
||||||
|
|
||||||
|
// Insall keyboard shortcut to change theme
|
||||||
|
export default function() {
|
||||||
|
const platform = window.navigator.platform;
|
||||||
|
const isMac = platform.indexOf('Mac') === 0;
|
||||||
|
|
||||||
|
document.onkeyup = function(e) {
|
||||||
|
const modifier = isMac ? e.altKey : e.ctrlKey;
|
||||||
|
if (modifier && e.which === 84) {
|
||||||
|
const ch = addons.getChannel();
|
||||||
|
ch.emit('shortcut-toggle-dark-mode');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,5 @@ import { create } from '@storybook/theming';
|
||||||
export default create({
|
export default create({
|
||||||
base: 'light',
|
base: 'light',
|
||||||
brandTitle: 'Rancher Storybook',
|
brandTitle: 'Rancher Storybook',
|
||||||
// brandUrl: '/https://github.com/rancher/dashboard',
|
|
||||||
brandImage: 'https://raw.githubusercontent.com/rancher/dashboard/master/assets/images/pl/rancher-logo.svg',
|
brandImage: 'https://raw.githubusercontent.com/rancher/dashboard/master/assets/images/pl/rancher-logo.svg',
|
||||||
});
|
});
|
||||||
|
|
@ -68,7 +68,7 @@ button,
|
||||||
color: var(--primary-text);
|
color: var(--primary-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus, &._focus {
|
&:focus, &.focused {
|
||||||
background-color: var(--primary-hover-bg);
|
background-color: var(--primary-hover-bg);
|
||||||
color: var(--primary-text);
|
color: var(--primary-text);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,7 @@ export default {
|
||||||
{{ resourceName }}
|
{{ resourceName }}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="numbers">
|
<div class="numbers">
|
||||||
|
<!-- @slot Optional slot to use as the title rather than showing the resource name -->
|
||||||
<slot name="title">
|
<slot name="title">
|
||||||
<span>{{ t('node.detail.glance.consumptionGauge.used') }}</span> <span>{{ t('node.detail.glance.consumptionGauge.amount', amountTemplateValues) }} <span class="ml-10 percentage">/ {{ formattedPercentage }}</span></span>
|
<span>{{ t('node.detail.glance.consumptionGauge.used') }}</span> <span>{{ t('node.detail.glance.consumptionGauge.amount', amountTemplateValues) }} <span class="ml-10 percentage">/ {{ formattedPercentage }}</span></span>
|
||||||
</slot>
|
</slot>
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A value which indicates which direction is better so we can change the color appropriately.
|
* A value which indicates which direction is better so we can change the color appropriately (Valid values: 'LESS' or 'MORE')
|
||||||
*/
|
*/
|
||||||
preferredDirection: {
|
preferredDirection: {
|
||||||
type: String,
|
type: String,
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,11 @@
|
||||||
"dev-debug": "node --inspect ./node_modules/.bin/nuxt",
|
"dev-debug": "node --inspect ./node_modules/.bin/nuxt",
|
||||||
"cy:open": "cypress open",
|
"cy:open": "cypress open",
|
||||||
"e2e:dev": "NODE_ENV=dev START_SERVER_AND_TEST_INSECURE=1 start-server-and-test dev https://localhost:8005 cy:open",
|
"e2e:dev": "NODE_ENV=dev START_SERVER_AND_TEST_INSECURE=1 start-server-and-test dev https://localhost:8005 cy:open",
|
||||||
"storybook": "start-storybook -s ./ -p 6006",
|
"storybook": "yarn run install-storybook && start-storybook -s .storybook/public,assets -p 6006",
|
||||||
"build-storybook": "build-storybook",
|
"build-storybook": "yarn run install-storybook && build-storybook -s .storybook/public,assets",
|
||||||
"install-storybook": "./scripts/storybook-install",
|
"install-storybook": "./scripts/storybook-install",
|
||||||
"remove-storybook": "./scripts/storybook-install -d"
|
"remove-storybook": "./scripts/storybook-install -d",
|
||||||
|
"remove-storybook-deps": "./scripts/storybook-install -r"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-ec2": "^3.1.0",
|
"@aws-sdk/client-ec2": "^3.1.0",
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,14 @@ const { spawn } = require("child_process");
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
let remove = false;
|
let remove = false;
|
||||||
if (process.argv.length > 2 && process.argv[2] === '-d') {
|
let doInstall = true;
|
||||||
|
if (process.argv.length > 2 && (process.argv[2] === '-d' || process.argv[2] === '-r')) {
|
||||||
remove = true;
|
remove = true;
|
||||||
console.log('Removing storybook from package.json');
|
console.log('Removing storybook from package.json');
|
||||||
|
|
||||||
|
if (process.argv[2] === '-d') {
|
||||||
|
doInstall = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const rootFolder = path.resolve(__dirname, '..');
|
const rootFolder = path.resolve(__dirname, '..');
|
||||||
|
|
@ -61,7 +66,7 @@ async function main() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (didChange) {
|
if (didChange && doInstall) {
|
||||||
console.log('Updating dependencies...');
|
console.log('Updating dependencies...');
|
||||||
await yarnInstall();
|
await yarnInstall();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,29 +19,29 @@ export default {
|
||||||
},
|
},
|
||||||
icon: {
|
icon: {
|
||||||
description: 'Optional icon to show before the label'
|
description: 'Optional icon to show before the label'
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const Template = (args, { argTypes}) => ({
|
const Template = (args, { argTypes, events }) => ({
|
||||||
components: { Banner },
|
components: { Banner },
|
||||||
props: Object.keys(argTypes),
|
props: Object.keys(argTypes),
|
||||||
// props: argTypes,
|
template: '<Banner v-on="events" v-bind="$props" />',
|
||||||
template: '<Banner v-bind="$props" />',
|
data: () => ({ events }),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const Primary = Template.bind({});
|
export const Primary = Template.bind({});
|
||||||
Primary.args = {
|
Primary.args = {
|
||||||
label: 'Banner Component - Primary',
|
label: 'Banner Component - Primary',
|
||||||
closable: false,
|
closable: false,
|
||||||
color: 'primary'
|
color: 'primary',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Info = Template.bind({});
|
export const Info = Template.bind({});
|
||||||
Info.args = {
|
Info.args = {
|
||||||
label: 'Banner Component - Info',
|
label: 'Banner Component - Info',
|
||||||
closable: false,
|
closable: false,
|
||||||
color: 'info'
|
color: 'info',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Warning = Template.bind({});
|
export const Warning = Template.bind({});
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { Meta } from '@storybook/addon-docs';
|
||||||
|
|
||||||
<style>{``}</style>
|
<style>{``}</style>
|
||||||
|
|
||||||
<Meta title="Components/Buttons" />
|
<Meta title="Styling/Buttons" />
|
||||||
|
|
||||||
# Buttons
|
# Buttons
|
||||||
|
|
||||||
|
|
@ -19,10 +19,10 @@ e.g.
|
||||||
Use class `role-primary`:
|
Use class `role-primary`:
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
<button class="btn role-primary">Primary Button</button>
|
<button className="btn role-primary">Primary Button</button>
|
||||||
<button class="btn role-primary" disabled>Primary Button</button>
|
<button className="btn role-primary" disabled>Primary Button</button>
|
||||||
<button class="btn role-primary _focus">Primary Button (Focus)</button>
|
<button className="btn role-primary focused">Primary Button (Focus)</button>
|
||||||
<button class="btn role-primary _hover">Primary Button (Hover)</button>
|
<button className="btn role-primary _hover">Primary Button (Hover)</button>
|
||||||
|
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
|
|
||||||
|
|
@ -31,10 +31,24 @@ Use class `role-primary`:
|
||||||
Use class `role-secondary`:
|
Use class `role-secondary`:
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
<button class="btn role-secondary">Secondary Button</button>
|
<button className="btn role-secondary">Secondary Button</button>
|
||||||
<button class="btn role-secondary" disabled>Secondary Button</button>
|
<button className="btn role-secondary" disabled>Secondary Button</button>
|
||||||
<button class="btn role-secondary _focus">Secondary Button (Focus)</button>
|
<button className="btn role-secondary focused">Secondary Button (Focus)</button>
|
||||||
<button class="btn role-secondary _hover">Secondary Button (Hover)</button>
|
<button className="btn role-secondary _hover">Secondary Button (Hover)</button>
|
||||||
|
|
||||||
|
<br/><br/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Tertiary Button
|
||||||
|
|
||||||
|
Use class `role-tertiary`:
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<button className="btn role-tertiary">Tertiary Button</button>
|
||||||
|
<button className="btn role-tertiary" disabled>Tertiary Button</button>
|
||||||
|
<button className="btn role-tertiary focused">Tertiary Button (Focus)</button>
|
||||||
|
<button className="btn role-tertiary _hover">Tertiary Button (Hover)</button>
|
||||||
|
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { Meta, Canvas, Story } from '@storybook/addon-docs';
|
||||||
|
import Banner from '../components/Banner.vue';
|
||||||
|
|
||||||
|
<style>{``}</style>
|
||||||
|
|
||||||
|
<Meta title="Examples/Form" />
|
||||||
|
|
||||||
|
# Form Example
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
<input type="text" value="Standard HTML input"/>
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { Meta } from '@storybook/addon-docs';
|
||||||
|
import icons from '~/assets/fonts/icons/selection.json';
|
||||||
|
|
||||||
|
<style>{`
|
||||||
|
.sb-icons {
|
||||||
|
// display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sb-icon {
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: 1px solid #777;
|
||||||
|
margin: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 220px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sb-icon > i {
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
|
||||||
|
<Meta title="Assets/Icons" />
|
||||||
|
|
||||||
|
# Icons
|
||||||
|
|
||||||
|
Icons are created using the standard HTML <i> element with the class `icon` and the class name of the icon, as shown below.
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
<pre><i class="icon icon-show" /></pre>
|
||||||
|
|
||||||
|
<br/><br/>
|
||||||
|
<div className="sb-icons">
|
||||||
|
{icons.icons.map((icon, index) => (
|
||||||
|
<div className="sb-icon" key={index}>
|
||||||
|
<div>{function(icon) { const name = icon.properties.name.split(','); return `icon-${name[0]}`}(icon)}</div>
|
||||||
|
<i className={function(icon) { const name = icon.properties.name.split(','); return `icon icon-${name[0]}`; }(icon)} />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
@ -1,110 +0,0 @@
|
||||||
import { Meta } from '@storybook/addon-docs';
|
|
||||||
|
|
||||||
<Meta title="Introduction" />
|
|
||||||
|
|
||||||
<style>{`
|
|
||||||
.subheading {
|
|
||||||
--mediumdark: '#999999';
|
|
||||||
font-weight: 900;
|
|
||||||
font-size: 13px;
|
|
||||||
color: #999;
|
|
||||||
letter-spacing: 6px;
|
|
||||||
line-height: 24px;
|
|
||||||
text-transform: uppercase;
|
|
||||||
margin-bottom: 12px;
|
|
||||||
margin-top: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link-list {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
grid-template-rows: 1fr 1fr;
|
|
||||||
row-gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 620px) {
|
|
||||||
.link-list {
|
|
||||||
row-gap: 20px;
|
|
||||||
column-gap: 20px;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (-ms-high-contrast:none) {
|
|
||||||
.link-list {
|
|
||||||
display: -ms-grid;
|
|
||||||
-ms-grid-columns: 1fr 1fr;
|
|
||||||
-ms-grid-rows: 1fr 1fr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.link-item {
|
|
||||||
display: block;
|
|
||||||
padding: 20px 30px 20px 15px;
|
|
||||||
border: 1px solid #00000010;
|
|
||||||
border-radius: 5px;
|
|
||||||
transition: background 150ms ease-out, border 150ms ease-out, transform 150ms ease-out;
|
|
||||||
color: #333333;
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link-item:hover {
|
|
||||||
border-color: #1EA7FD50;
|
|
||||||
transform: translate3d(0, -3px, 0);
|
|
||||||
box-shadow: rgba(0, 0, 0, 0.08) 0 3px 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link-item:active {
|
|
||||||
border-color: #1EA7FD;
|
|
||||||
transform: translate3d(0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.link-item strong {
|
|
||||||
font-weight: 700;
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link-item img {
|
|
||||||
height: 40px;
|
|
||||||
width: 40px;
|
|
||||||
margin-right: 15px;
|
|
||||||
flex: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link-item span {
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tip {
|
|
||||||
display: inline-block;
|
|
||||||
border-radius: 1em;
|
|
||||||
font-size: 11px;
|
|
||||||
line-height: 12px;
|
|
||||||
font-weight: 700;
|
|
||||||
background: #E7FDD8;
|
|
||||||
color: #66BF3C;
|
|
||||||
padding: 4px 12px;
|
|
||||||
margin-right: 10px;
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tip-wrapper {
|
|
||||||
font-size: 13px;
|
|
||||||
line-height: 20px;
|
|
||||||
margin-top: 40px;
|
|
||||||
margin-bottom: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tip-wrapper code {
|
|
||||||
font-size: 12px;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
`}</style>
|
|
||||||
|
|
||||||
# Welcome to the Rancher Dashboard Storybook
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
|
||||||
|
import { Meta } from "@storybook/addon-docs";
|
||||||
|
import icons from './provider-icons.json';
|
||||||
|
|
||||||
|
<style>{`
|
||||||
|
.sb-icons {
|
||||||
|
// display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reverse-filter {
|
||||||
|
}
|
||||||
|
|
||||||
|
.reverse-filter .sb-icon {
|
||||||
|
background: #000;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reverse-filter .sb-icon img {
|
||||||
|
filter: invert(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sb-icon {
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: 1px solid #777;
|
||||||
|
margin: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 220px;
|
||||||
|
height: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sb-icon > img {
|
||||||
|
margin: 10px;
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
|
||||||
|
<Meta title="Assets/Provider Images" />
|
||||||
|
|
||||||
|
# Provider Images
|
||||||
|
|
||||||
|
Images for various providers are included in the `assets/images/providers` folder.
|
||||||
|
|
||||||
|
<h2>Full Color Logos</h2>
|
||||||
|
|
||||||
|
<div className="sb-icons">
|
||||||
|
{icons.map((icon, index) => (
|
||||||
|
<div className="sb-icon" key={index}>
|
||||||
|
<div>{icon}</div>
|
||||||
|
<img src={function(i) { return `./images/providers/${i}.svg`; }(icon)} />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Single Color Logos</h2>
|
||||||
|
|
||||||
|
<div className="sb-icons">
|
||||||
|
{icons.map((icon, index) => (
|
||||||
|
<div className="sb-icon" key={index}>
|
||||||
|
<div>{icon}</div>
|
||||||
|
<img src={function(i) { return `./images/providers/${i}-black.svg`; }(icon)} />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Inverted with CSS - Single Color Logos</h2>
|
||||||
|
|
||||||
|
|
||||||
|
<div className="sb-icons reverse-filter ">
|
||||||
|
{icons.map((icon, index) => (
|
||||||
|
<div className="sb-icon" key={index}>
|
||||||
|
<div>{icon}</div>
|
||||||
|
<img src={function(i) { return `./images/providers/${i}-black.svg`; }(icon)} />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Storybook
|
# Storybook
|
||||||
|
|
||||||
By default the Storybook dependencies are not included in the main package file.
|
By default the Storybook dependencies are not included in the main package file (it adds a lot of weight to the install process).
|
||||||
|
|
||||||
If you run any of the targets:
|
If you run any of the targets:
|
||||||
|
|
||||||
|
|
@ -19,16 +19,24 @@ You can remove the Storybook dependencies with:
|
||||||
|
|
||||||
- yarn remove-storybook
|
- yarn remove-storybook
|
||||||
|
|
||||||
|
# Running Storybook
|
||||||
|
|
||||||
|
Just run the command:
|
||||||
|
|
||||||
|
```
|
||||||
|
yarn storybook
|
||||||
|
```
|
||||||
|
|
||||||
|
You can access Storybook at the URL: http://127.0.0.1:6006
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
- Make 'Introduction' the landing story
|
- Port design-system pages to Storybook
|
||||||
- Add light/dark theme support with keyboard shortcut (Command-T) to toggle
|
|
||||||
- Add Icons page (maybe generated from the info in assets/fonts/icons/variables.scss)
|
|
||||||
- Add Typography page (for headers etc and padding and margin classes)
|
- Add Typography page (for headers etc and padding and margin classes)
|
||||||
- Write short developer reference for how to document components and write stories
|
- Write short developer reference for how to document components and write stories
|
||||||
- Build out stories for components
|
- Build out stories for components
|
||||||
- Auto-build via CI and publish to Github pages ?
|
- Auto-build via CI and publish to Github pages ?
|
||||||
- Add some content to the Introduction page
|
- Add some content to the Welcome page
|
||||||
- Get i18n working
|
- Get i18n working
|
||||||
- Get store working (where required by a component)
|
- Get store working (where required by a component)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
import { Meta } from "@storybook/addon-docs";
|
||||||
|
|
||||||
|
<Meta title="Welcome" />
|
||||||
|
|
||||||
|
# Rancher Storybook
|
||||||
|
|
||||||
|
Welcome to the Rancher Storybook.
|
||||||
|
|
||||||
|
This Storybook documents the components and the design system that is used in the Rancher UIs.
|
||||||
|
|
||||||
|
> Note that you can toggle between dark and light modes using the moon/sun icon the toolbar or with the keyboard shortcut CMD+T (Mac) or CTRL+T (Windows/Linux).
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
import ConsumptionGauge from '@/components/ConsumptionGauge';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Components/ConsumptionGauge',
|
||||||
|
component: ConsumptionGauge,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Story = (args, { argTypes}) => ({
|
||||||
|
components: { ConsumptionGauge },
|
||||||
|
props: Object.keys(argTypes),
|
||||||
|
methods: {
|
||||||
|
formatter(value) {
|
||||||
|
const valueAsArray = value.toString().split('');
|
||||||
|
|
||||||
|
valueAsArray.splice(1, 0, ',');
|
||||||
|
|
||||||
|
return valueAsArray.join('');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `
|
||||||
|
<div style="width: 300px;">
|
||||||
|
<ConsumptionGauge v-bind="$props"/>
|
||||||
|
</div>`,
|
||||||
|
});
|
||||||
|
|
||||||
|
Story.story = { name: 'ConsumptionGauge' };
|
||||||
|
Story.args = {
|
||||||
|
used: 300,
|
||||||
|
capacity: 789,
|
||||||
|
units: 'GB',
|
||||||
|
resourceName: 'DISK'
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
import IconIsDefault from '@/components/formatter/IconIsDefault';
|
||||||
|
|
||||||
|
const DefaultColumnState = {
|
||||||
|
name: 'builtIn',
|
||||||
|
value: 'builtIn',
|
||||||
|
formatter: 'IconIsDefault'
|
||||||
|
};
|
||||||
|
|
||||||
|
const DefaultNotTrue = { builtIn: false };
|
||||||
|
const DefaultIsTrue = { builtIn: true };
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Components/Formatters/IconIsDefault',
|
||||||
|
component: IconIsDefault,
|
||||||
|
decorators: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DefaultStory = () => ({
|
||||||
|
components: { IconIsDefault },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
row: DefaultNotTrue,
|
||||||
|
col: DefaultColumnState
|
||||||
|
};
|
||||||
|
},
|
||||||
|
template: `<IconIsDefault :row="row" :col="col" />`
|
||||||
|
});
|
||||||
|
|
||||||
|
DefaultStory.story = { name: 'Input Not Default' };
|
||||||
|
|
||||||
|
export const IsDefault = () => ({
|
||||||
|
components: { IconIsDefault },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
row: DefaultIsTrue,
|
||||||
|
col: DefaultColumnState
|
||||||
|
};
|
||||||
|
},
|
||||||
|
template: `<IconIsDefault :row="row" :col="col" />`
|
||||||
|
});
|
||||||
|
|
||||||
|
IsDefault.story = { name: 'Input Is Default' };
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
import PercentageBar from '@/components/PercentageBar';
|
||||||
|
import { DescribeSpotPriceHistoryCommand } from '@aws-sdk/client-ec2';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'Components/PercentageBar',
|
||||||
|
component: PercentageBar,
|
||||||
|
argTypes: {
|
||||||
|
preferredDirection: {
|
||||||
|
control: {
|
||||||
|
type: 'select',
|
||||||
|
options: ['LESS', 'MORE']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Story = (args, { argTypes}) => ({
|
||||||
|
components: { PercentageBar },
|
||||||
|
props: Object.keys(argTypes),
|
||||||
|
// props: {
|
||||||
|
// value1: { default: number('First Value', 67) },
|
||||||
|
// value2: { default: number('Second Value', 83) },
|
||||||
|
// value3: { default: number('Third Value', 97) },
|
||||||
|
// },
|
||||||
|
template: `
|
||||||
|
<div style="width: 300px">
|
||||||
|
<PercentageBar v-bind="$props"/>
|
||||||
|
</div>`,
|
||||||
|
});
|
||||||
|
|
||||||
|
Story.story = { name: 'PercentageBar' };
|
||||||
|
Story.args = {
|
||||||
|
value: 45,
|
||||||
|
showPercentage: true.valueOf,
|
||||||
|
preferredDirection: 'LESS'
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -10,3 +10,19 @@ pre.sbdocs {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BODY, .sbdocs-wrapper {
|
||||||
|
background: var(--body-bg) !important;
|
||||||
|
color: var(--body-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
H1, H2, H3, H4, H5, H6, P {
|
||||||
|
color: var(--body-text) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
CODE:not(.language-jsx) {
|
||||||
|
background-color: var(--box-bg) !important;;
|
||||||
|
border: 1px solid var(--border) !important;;
|
||||||
|
border-radius: var(--border-radius) !important;;
|
||||||
|
color: var(--body-text) !important;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
[
|
||||||
|
"aliyunecs",
|
||||||
|
"amazonec2",
|
||||||
|
"amazoneks",
|
||||||
|
"azureaks",
|
||||||
|
"digitalocean",
|
||||||
|
"equinix",
|
||||||
|
"googlegke",
|
||||||
|
"k3s",
|
||||||
|
"kubernetes",
|
||||||
|
"linodelke",
|
||||||
|
"minikube",
|
||||||
|
"oci",
|
||||||
|
"openstack",
|
||||||
|
"otc",
|
||||||
|
"pinganyunecs",
|
||||||
|
"pnap"
|
||||||
|
]
|
||||||
Loading…
Reference in New Issue