From d819bf27239b9e0d34dcb69e1d1dd9e4c5e3fd7f Mon Sep 17 00:00:00 2001 From: Wired Earp Date: Tue, 19 Dec 2017 12:26:16 +0100 Subject: [PATCH] Support async loading + clean up a little --- Gruntfile.js | 24 +----------- docs/dist/TEST.html | 38 +++++++++++++++++++ docs/dist/lunr.json | 2 +- docs/src/xhtml/TEST.xhtml | 17 +++++++++ .../concepts/gui.Document.js | 22 ++++++++++- 5 files changed, 77 insertions(+), 26 deletions(-) create mode 100644 docs/dist/TEST.html create mode 100644 docs/src/xhtml/TEST.xhtml diff --git a/Gruntfile.js b/Gruntfile.js index 9a4813da0..9f80c356b 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -102,27 +102,6 @@ module.exports = function(grunt) { } }, - tsjs: { - // setup 'ts.js' - dev: { - files: { - 'temp/ts.js': 'src/runtime/ts.js' - } - }, - // setup 'ts.js' for jasmine tests - jasmine: { - files: { - 'temp/ts.js': 'src/runtime/ts.js' - } - }, - // setup 'ts.js' for CDN - cdn: { - files: { - 'temp/ts.js': 'src/runtime/ts.js' - } - } - }, - tsless: { // concatenate the LESS (so that devs may copy-paste it from the web) cdn: { @@ -472,7 +451,6 @@ module.exports = function(grunt) { function generateJsConcurrent(target = 'cdn') { return [ 'edbml', // edbml -> js - `tsjs:${target}`, [ // generate ts.js `tsless:${returnDevForJasmine(target)}`, // generate ts.less @@ -588,7 +566,7 @@ module.exports = function(grunt) { * @returns {Array} */ function getcombobuilds() { - return ['temp/ts.js'].concat(getapibuilds()).concat(getguibuilds()); + return getapibuilds().concat(getguibuilds()); } /** diff --git a/docs/dist/TEST.html b/docs/dist/TEST.html new file mode 100644 index 000000000..1ed1aa4b2 --- /dev/null +++ b/docs/dist/TEST.html @@ -0,0 +1,38 @@ + + + + + Testing + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/dist/lunr.json b/docs/dist/lunr.json index 4ad6fbe91..1f970fa35 100644 --- a/docs/dist/lunr.json +++ b/docs/dist/lunr.json @@ -1 +1 @@ -[{"title":"Automagic Focus","href":"appendix/autofocus/index.html","content":"Automagic focus On this page weve added a yellow outline to the focused element Keyboard support is always a work in progress but we have a system to ensure that something is in theory always focused Note that there is no default focus but you can set the default focus with the HTML autofocus attribute In Notifications and Asides well always attempt to focus something even if we cant find any element with the autofocus attribute Click the buttons to see Open the Notification Open the Aside TODO Note about focus on mobile device Aside content Open next aside Open next aside Thanks now close them It appears we have a bug If you do click that button the focus will be lost But you can try to close them one at a time by clicking the X in the corner If you find a bug or need a feature Create GitHub Issue"},null,{"title":"Automated Layout","href":"appendix/autolayout/index.html","content":"Automated Layout var LayoutModel tsuiModelextend topBar false toolBarBefore false toolBarAfter false sideBarBefore false sideBarAfter false new LayoutModeloutput tsform margintop 22px hack for empty SPAN labelspan fontweight 300 edbmldeclareedbmliSNtu1asfunction edbml use strict var out edbmlout set edbmlset txt edbmlsafetext val edbmlsafeattr layout edbmlinputLayoutModel if layouttopBar outhtml if layoutsideBarBefore outhtml SideBar content Optional SideBar footer if layouttoolBarBefore outhtml outhtml Automated layout We donapost have a lot of layouts yet but the page will automatically transform into a classic three column layout with fixed headers and footer as certain components are added You can toggle these components in the checklist function checkboxtext prop localhost if localhost locationhostname localhost outhtml var 1 setfunctionvalue checked layoutprop checked this outhtml txttext checkboxTopBar topBar checkboxToolBar before Main DEPRECATED toolBarBefore true checkboxToolBar after Main DEPRECATED toolBarAfter true checkboxSideBar before Main sideBarBefore checkboxSideBar after Main sideBarAfter outhtml TODO Save this page in mobile breakpoint if layouttoolBarAfter outhtml if layoutsideBarAfter outhtml SideBar content Optional SideBar footer return outwrite withInstructions input name layout type LayoutModel If you find a bug or need a feature Create GitHub Issue"},{"title":"Colors","href":"appendix/colors/index.html","content":"Colors Colors Here you can see a list of colors you can use in Tradeshift apps edbmldeclareedbml1JJU8I0asfunction edbml use strict var out edbmlout att edbmlatt txt edbmlsafetext val edbmlsafeattr var colors tsblack rgb303030 tswhite rgb255255255 tsdarkdarker rgb333333 tsdarkdark rgb434343 tsdark rgb535353 tsdarklite rgb636363 tsdarkliter rgb737373 tsmediumdarkest rgb979797 tsmediumdarker rgb107107107 tsmediumdark rgb117117117 tsmedium rgb127127127 tsmediumlite rgb137137137 tsmediumliter rgb147147147 tsmediumlitest rgb175175175 tslitedarker rgb205205205 tslitedark rgb215215215 tslite rgb225225225 tslitelite rgb235235235 tsliteliter rgb245245245 tsgreen rgb11417772 tsgreendark rgb9415752 tsgreendarker rgb7413732 tsgreenlite rgb13419792 tsgreentext tswhite tslitegreen rgb178215130 tsdarkgreen rgb248463 tsblue rgb32160233 tsbluedark rgb12140213 tsbluedarker rgb0120193 tsbluelite rgb43180253 tsblueliter rgb88184239 tsbluetext tswhite tsliteblue rgb236247253 tslitebluedark rgb220241253 tsdustblue rgb5499117 tsdarkblue rgb246384 tsred rgb19100 tsreddark rgb17100 tsreddarker rgb15100 tsredlite rgb23100 tsredtext tswhite tsdarkred rgb2333232 tsdarkredlite rgb248229229 tsdarkredtext tswhite tsyellow rgb253254213 tsyellowdark rgb244242201 tsyellowtext rgb12711572 tsorangeliter rgb250 236 217 tsorangelite rgb245 224 184 tsorange rgb230 153 0 tsorangedark rgb209 91 0 tsorangedarker rgb66 40 0 tspurple rgb14852200 tspurpledark rgb12845173 tspurpledarker rgb10825153 tspurplelite rgb16658224 tspurpletext tswhite colorsforEachfunctioncolorSet outhtml for var colorName in colorSet var colorCode colorSetcolorName outhtml commat txtcolorName txtcolorCode outhtml return outwrite "},{"title":"Appendix","href":"appendix/index.html","content":"Appendix You can make great Tradeshift apps by studying these pages that didnt fit elsewhere in the menu structure Implement responsive design with some handy CSS classnames Get an overview of the color scheme used in Tradeshift See some basic examples of the general typography Learn the primitive dialect of Markdown that we use Observe the principle of automated layout in action Be aware that UI components will attempt to manage the focus If you find a bug or need a feature Create GitHub Issue"},null,{"title":"Markdown","href":"appendix/markdown/index.html","content":"Markdown If you find a bug or need a feature Create GitHub Issue"},null,null,{"title":"Typography","href":"appendix/typo/index.html","content":"Typography Heres a very basic overview of the typography used in Tradeshift Apps H1fontsize 36px tsfontsizexxbig H2fontsize 24px tsfontsizexbig H3fontsize 18px tsfontsizebig Normal paragraph of textfontsize 14px tsfontsize Unordered List Ordered List If you find a bug or need a feature Create GitHub Issue"},null,null,null,null,null,null,null,null,{"title":"API-only Components","href":"components/api-only.html","content":"APIonly components These components will insert themselves into the DOM and generally dont come with a HTML API Some of them are known to affect the general page layout TopBar The TopBar provides tabs for navigation and buttons for contextual actions Beware that this API will be replaced be the tsuiHeader in a future release tsuiTopBarbuttons label Button type tsprimary label Button type tssecondary label Button onclick function consolelogClicked tsuiTopBarbuttons label Button type tsprimary label Button type tssecondary label Button onclick function consolelogClicked Main TabBar The Main TabBar provides second level tabbed navigation Beware that this API will be replaced be the tsuiHeader in a future release tsuiTabBartabs label Tab One label Tab Two label Tab Three onselect function consolelogSelected tsuiTabBartabs label Tab One label Tab Two label Tab Three onselect function consolelogSelected Main ToolBar The Main ToolBar features a Search and even more buttons for contextual actions Beware that this API will be replaced be the tsuiHeader in a future release tsuiToolBarbuttons label Button type tsprimary label Button type tssecondary label Button onclick function consolelogClicked search info Search amongst the things onsearch functionvalue consolelogvalue tsuiToolBarbuttons label Button type tsprimary label Button type tssecondary label Button onclick function consolelogClicked search info Search amongst the things onsearch functionvalue consolelogvalue Footer The Footer is positioned below the Main area where it usually functions to display some buttons But the Footer also supports actions which are reserved for working with selected objects of any kind as well as a Pager and a dedicated Collaboration button tsuiFooterbuttons label Button type tsprimary label Button type tssecondary label Button onclick consolelogButton clicked actions label Action icon tsiconfollowed label Action icon tsiconfavorites label Action icon tsiconcode onclick consolelogAction clicked statusHello World tsuiFooterbuttons label Button type tsprimary label Button type tssecondary label Button onclick consolelogButton clicked actions label Action icon tsiconfollowed label Action icon tsiconfavorites label Action icon tsiconcode onclick consolelogAction clicked statusHello World DatePicker A easy way to select dates tsuiDatePicker title Your Birthday value 19840523 min 19840101 max 19851224 onselect functiondate tsuiNotificationsuccessdate selected thisclose onclosed function thisdispose open tsuiDatePicker title Your Birthday value 19840523 min 19840101 max 19851224 onselect functiondate tsuiNotificationsuccessdate selected thisclose onclosed function thisdispose open Dialog Works much like the JavaScript confirm method tsuiDialogconfirmShow the Warning dialog Show It Nope onaccept function tsuiDialogwarningShow the Danger dialog Of Course onaccept function tsuiDialogdangerThat could be dangerous Got it tsuiDialogconfirmShow the Warning dialog Show It Nope onaccept function tsuiDialogwarningShow the Danger dialog Of Course onaccept function tsuiDialogdangerThat could be dangerous Got it Notification Themed variants of the JavaScript alert method tsuiNotificationsuccessNotificationsuccess tsuiNotificationinfoNotificationinfo tsuiNotificationwarningNotificationwarning tsuiNotificationerrorNotificationerror tsuiNotificationsuccessNotificationsuccess tsuiNotificationinfoNotificationinfo tsuiNotificationwarningNotificationwarning tsuiNotificationerrorNotificationerror Note A nice way to inform the user about something in general This is not for status messages The Note attaches to the top of the page so you will have to scroll back up tsuiNote icon tsiconheart text This is the Note Thanks for scrolling up onclose function tsuiNotificationsuccessThe Note is gone tsuiNote icon tsiconheart text This is the Note Thanks for scrolling up onclose function tsuiNotificationsuccessThe Note is gone UserCard Show some details about a user tsuiUserCard id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Wired Earp image assetswiredearppng title EDB Programmer role Gentleman Spy email jmotradeshiftcom company Tradeshift companyUrl httptradeshiftcom open tsuiUserCard id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Wired Earp image assetswiredearppng title EDB Programmer role Gentleman Spy email jmotradeshiftcom company Tradeshift companyUrl httptradeshiftcom open If you find a bug or need a feature Create GitHub Issue"},{"title":"Aside HTML","href":"components/asides/index.html","content":"Aside Sidepanel used for small user interactions such as selecting a date The Aside component must be created with a child component Panel Aside content Aside content You can create the Aside wherever you like just make sure that its positioned outside of the Main element when it opens Main content Aside content Main content Aside content Adding a header The datatstitle attribute configures the Aside with a nice header Aside content Aside content You can color the header by assigning any of the classnames tsbgblue tsbggreen tsbgred and tsbgpurple to the Aside element itself Opening the aside The datatsopen attribute can be flipped to toggle the Aside Aside content Aside content Lets try that with jQuery myasideattrdatatsopen true myasideattrdatatsopen true Adding some tabs If an Aside contains more than one Panel we will automatically create a TabBar to switch between the panels like in this example Aside content Aside content Aside content Aside content The tabs can also be created programatically In that case the panel switching mechanism must be implemented manually somehow tsuigetaside3 aside asidetabs label Tab 1 onselect function consolelogPanel one label Tab 2 onselect function consolelogPanel two open tsuigetaside3 aside asidetabs label Tab 1 onselect function consolelogPanel one label Tab 2 onselect function consolelogPanel two open You can also mix the two approaches to dynamically update tabs that were created with Panel elements This will for example assign an onselect callback to the third tab tsuigetmyaside aside var tabs asidetabs tabs2onselect function consolelogselected tsuigetmyaside aside var tabs asidetabs tabs2onselect function consolelogselected To remove all dynamically created tabs you can simply clear the tab collection tsuigetmyaside aside asidetabsclear tsuigetmyaside aside asidetabsclear Adding some buttons Its common for Asides to show a group of buttons usually following a set of form fields To make sure that they always look the same the certified way to add this group of buttons is via a Buttons menu form fields here Submit Changes Cancel Everything form fields here Submit Changes Cancel Everything Showing the spinner The datatsbusy attribute can be set to show the spinner Aside content Aside content Lets try that with jQuery var aside myaside asideattrdatatsbusy Loading asideattrdatatsopen true setTimeoutfunction asideattrdatatsbusy setTimeoutfunction asideattrdatatsopen false 500 1500 var aside myaside asideattrdatatsbusy Loading asideattrdatatsopen true setTimeoutfunction asideattrdatatsbusy setTimeoutfunction asideattrdatatsopen false 500 1500 Tracking the state You can setup inline callbacks to be invoked when the aside changes state using one of onopen onopened onclose and onclosed You can also do this with event listeners if you like Aside content Aside content Stacking Asides Asides will automatically stack themselves whenever new asides open The old Asides will slide elegantly to the right The new Aside will float the top of the zindex Bacon ipsum dolor sit plsesnack jerky pork belly short loin sausage andouille kevin capicola ham hamburger doner Shank prosciutto flank kevin ribeye short ribs swine ham pork porchetta spare ribs kielbasa beef ribs Prosciutto pancetta shank boudin Corned beef shoulder capicola turducken prosciutto pork belly sirloin shankle brisket chuck leberkas tail beef Sirloin meatloaf pastrami beef ribs Ball tip pastrami landjaeger brisket Tradeshift strip steak short loin pancetta meatball corned beef tenderloin beef ribs spare ribs Tradeshift sausage strip steak ham ribeye pork loin meatball turkey corned beef shoulder Leberkas jerky sirloin boudin turducken ham hock pastrami Doner pig boudin sausage ball tip leberkas ground round beef jowl kielbasa tongue shankle spare ribs tail shoulder Fatback pork kielbasa ham doner pig short loin short ribs pancetta Pancetta jerky biltong short loin capicola beef Pork belly strip steak venison brisket shoulder beef filet mignon shank tenderloin tritip ground round shankle cow Tradeshift salami burger mit invoice pastrami shankle venison meatball pork belly capicola ribeye sirloin doner Aside Tail kielbasa beef ribs landjaeger pork belly Tbone pig andouille doner ham sirloin short ribs meatloaf salami strip steak tenderloin short loin tritip pork loin Pastrami jowl sirloin kevin jerky filet mignon bacon pork chop brisket pancetta Spare ribs ground round pork belly pork chop doner swine fatback bresaola Picanha beef ribs burgdoggen bacon sausage rump Porchetta turkey ribeye tenderloin landjaeger spare ribs strip steak pork belly tbone Tenderloin tbone ham doner corned beef chuck fatback ground round short ribs tritip Landjaeger ribeye brisket boudin tongue pork kevin frankfurter Swine capicola filet mignon cow spare ribs ribeye salami sausage porchetta hamburger short ribs corned beef Open next aside Open next aside Thanks now close them If you find a bug or need a feature Create GitHub Issue"},{"title":"Aside JS","href":"components/asides/js.html","content":"Asides JS You can get a hold of the Aside component and control it with JavaScript tsuigetmyaside aside you can pass an element instead of an ID asideopen asideclose asidetoggle asidetitleUpdated title Tracking with methods You can overwrite the methods onopen onopened onclose and onclosed to do something whenever the aside changes state asideonopen function consolelogAside will open If you return false in methods onopen and onclose the aside will respect that Tracking with events You can also monitor the asides with DOM event listeners function debuge consolelogetype etarget documentaddEventListenertsopen debug documentaddEventListenertsopened debug documentaddEventListenertsclose debug documentaddEventListenertsclosed debug The events tsopen and tsclose can be blocked with epreventDefault to prevent the aside from changing state If you find a bug or need a feature Create GitHub Issue"},{"title":"","href":"components/asides/tabs.html","content":""},null,null,null,null,{"title":"StatusBar","href":"components/bars/statusbar-DEPRECATED.html","content":"Main StatusBar is deprecated This component is deprecated in favor of the Footer In a future release the TopBar and TabBar and ToolBar will be collected in the equivalent Header You can still use the StatusBar as an inline component Although the StatusBar can display status messages and features a Pager its perfectly alright to use it just to show some buttons You can show a status message with basic Markdown support tsuiStatusBarmessage The status message supports bold and italic text tsuiStatusBarmessage The status message supports bold and italic text If you call linkable you can also some links in the message Beware of phishing tsuiStatusBarlinkablemessage Please visit Tradeshifthttpwwwtradeshiftcom tsuiStatusBarlinkablemessage Please visit Tradeshifthttpwwwtradeshiftcom You can pass a callback function to be invoked whenever a link is clicked tsuiStatusBarlinkablefunction onclickurl tsuiNotificationsuccessurl thismessageThanks messagePlease click the linkThe URL can be any string tsuiStatusBarlinkablefunction onclickurl tsuiNotificationsuccessurl thismessageThanks messagePlease click the linkThe URL can be any string StatusBarbuttons Add buttons to the StatusBar with the buttons method This both sets and gets If you omit the argument youll get the current buttons jQuery style tsuiStatusBarbuttons label Primary type tsprimary label Secondary type tssecondary label Tertiary One label Tertiary Two tsuiStatusBarbuttons label Primary type tsprimary label Secondary type tssecondary label Tertiary One label Tertiary Two You can use array methods like push pop shift unshift splice reverse and so on to manage buttons Just note that the buttons length is readonly The buttons type property works like the CSS class for a regular Button The StatusBar will automatically sort all buttons from primary to tertiary If theres more than one tertiary button these will be pushed to an Aside In the mobile breakpoint all the buttons will be pushed to an Aside Buttons wont actually do anything unless you define the onclick method tsuiStatusBarbuttonssplice0 1 label Click me type tsprimary onclick function thislabel Thanks tsuiStatusBarbuttonssplice0 1 label Click me type tsprimary onclick function thislabel Thanks Fortunately you can always change what happens when a button gets clicked tsuiStatusBarbuttonsforEachfunctionbutton index buttonlabel Button index 1 buttononclick function tsuiNotificationsuccessthislabel tsuiStatusBarbuttonsforEachfunctionbutton index buttonlabel Button index 1 buttononclick function tsuiNotificationsuccessthislabel Query buttons You can locate buttons by index in the buttons collection But since this isnt likely to match the order in which they appear on screen its easier to give the buttons an id and find them using buttonsget var buttons tsuiStatusBarbuttons buttonspush id examplebutton var button buttonsgetexamplebutton buttonlabel My Button buttontype tssecondary var buttons tsuiStatusBarbuttons buttonspush id examplebutton var button buttonsgetexamplebutton buttonlabel My Button buttontype tssecondary Hide buttons You can hide and show buttons You can also toggle visible tsuiStatusBarbuttonsforEachfunctionbutton ifbuttonvisible buttonhide else buttonshow tsuiStatusBarbuttonsforEachfunctionbutton ifbuttonvisible buttonhide else buttonshow Disable buttons You can disable and enable buttons You can also toggle disabled tsuiStatusBarbuttonsforEachfunctionbutton ifbuttondisabled buttonenable else buttondisable tsuiStatusBarbuttonsforEachfunctionbutton ifbuttondisabled buttonenable else buttondisable Busy buttons We can display a temporary progress indicator with the busy and done methods var button tsuiStatusBarbuttons0 buttonbusy setTimeoutfunction buttondone 1000 var button tsuiStatusBarbuttons0 buttonbusy setTimeoutfunction buttondone 1000 The busy method supports an optional status message var button tsuiStatusBarbuttons0 buttonbusyMaking progress setTimeoutfunction buttondone 1000 var button tsuiStatusBarbuttons0 buttonbusyMaking progress setTimeoutfunction buttondone 1000 Button groups You can also group buttons in arrays to create button groups that look like this tsuiStatusBarbuttons label Normal label Normal label Accept type tsprimary label Reject type tsdanger tsuiStatusBarbuttons label Normal label Normal label Accept type tsprimary label Reject type tsdanger You can of course also create grouped buttons with icons instead of text var group tsuiStatusBarbuttons2 grouppush icon tsiconother type tssecondary var group tsuiStatusBarbuttons2 grouppush icon tsiconother type tssecondary Heres a summary of the buttons collection and button model StatusBarpager You can initialize a Pager in the StatusBar tsuiStatusBarpager pages 23 page 0 onselect functionpage consolelogpage tsuiStatusBarpager pages 23 page 0 onselect functionpage consolelogpage To make room for the Pager and to make it look nice centeraligned any potential buttons in the StatusBar will be moved into a menu Note that even primary buttons will be hidden when the StatusBar features a Pager TODO Explain how the statusbar behaves in mobile view Also we might need to split long status messages into two lines when the window is resizing For now well just pretend that all users have desktopsized screens Inline Statusbar The responsive StatusBar is a work in progress This is a dev preview Assign datatsStatusBar to a footer or menu to initialize it as a StatusBar Another attribute datatsmessage displays the message The StatusBar has no default outline so weve fitted ours with a dropshadow In your app any such outlining should be done under consideration of the neighboring elements You can get a hold of the component using a CSS selector and call any of the methods weve seen applicable to the Main ToolBar Notice what happens when we add content tsuigetmystatusbar statusbar statusbarbuttons label One type tsprimary label Two type tssecondary label Three pager pages 23 messageThe layout has changed tsuigetmystatusbar statusbar statusbarbuttons label One type tsprimary label Two type tssecondary label Three pager pages 23 messageThe layout has changed Because there is limited horizontal space available the StatusBar has snapped into a layout that is optimized for mobile phones The exact layout depends on the features you enable but you can in any case intercept this change with the onlayout callback var statusbar tsuigetmystatusbar statusbaronlayout function thismessageThe layout has changed again statusbarpagernull just to show that it works var statusbar tsuigetmystatusbar statusbaronlayout function thismessageThe layout has changed again statusbarpagernull just to show that it works This is a work in progress If you find a bug or need a feature Create GitHub Issue"},{"title":"TabBar","href":"components/bars/tabbar.html","content":"Main TabBar Second level navigation is in danger of becoming deprecated so please be cautious with this design pattern We can initialize the TabBar tabs with the the tabs method tsuiTabBartabs label Main TabBar label Inline TabBar but since the page already has tabs we will instead append a new tab to the existing collection If you omit the argument youll get the current tabs jQuery style var tabs tsuiTabBartabs tabspush label Bonus Tab onselect function var text thislabel selected tsuiNotificationsuccesstext var tabs tsuiTabBartabs tabspush label Bonus Tab onselect function var text thislabel selected tsuiNotificationsuccesstext You can use array methods like push pop shift unshift splice and so on to manage tabs just note that the tabs length is a readonly property Also note that tabs dont do anything by default so what happens at onselect is completely up to you Updating tabs We can at any time change what happens when a tab gets selected We can also change the tab label if we like although maybe this would be confusing for the user var tabs tsuiTabBartabs tabs2label Choose Me tabs2onselect function thislabel Thanks var tabs tsuiTabBartabs tabs2label Choose Me tabs2onselect function thislabel Thanks Selecting tabs We can programatically select a tab using one of these approaches tsuiTabBartabs2select tsuiTabBartabsselectedIndex 0 Querying tabs This will all become a lot easier if we give all the tabs an id and use tabsget var tabs tsuiTabBartabs tabssplice2 0 label Example Tab id exampletab tabsgetexampletabselect var tabs tsuiTabBartabs tabssplice2 0 label Example Tab id exampletab tabsgetexampletabselect Tabs icons You can add a tab with an icon if somehow that tab is special tsuiTabBartabspush label Icon Tab icon tsicontodo tsuiTabBartabspush label Icon Tab icon tsicontodo Tab counters You can add a counter to the tabs for whatever reason you like tsuiTabBartabsforEachfunctiontab tabcounter MathceilMathrandom 10 tsuiTabBartabsforEachfunctiontab tabcounter MathceilMathrandom 10 When the counter reaches zero it disappears tsuiTabBartabsforEachfunctiontab tabcounter tsuiTabBartabsforEachfunctiontab tabcounter Closeable tabs You can create closeable tabs but note that the tab must be selected before it can be closed You can return false in the onclose method to prevent the tab from closing if this would otherwise cause data loss tsuiTabBartabspush label Closeable Tab closeable true selected true onclose function tsuiNotificationsuccessthislabel closed tsuiTabBartabspush label Closeable Tab closeable true selected true onclose function tsuiNotificationsuccessthislabel closed NewTab button You can allow the user to create new tabs via a special button as seen in popular browsers Note that the button just triggers a callback and that the new tab must be created manually In the example below the selected property also selects the tab var tabs tsuiTabBartabs tabsshowNewfunction onclick tabspush label My New Tab selected true var tabs tsuiTabBartabs tabsshowNewfunction onclick tabspush label My New Tab selected true If you regret this later on you can also hide the button tsuiTabBartabshideNew tsuiTabBartabshideNew Heres a summary of the tabs collection and tab model TabBarbuttons Its perfectly alright to add buttons to the TabBar either to avoid wasting space on a separate ToolBar or because the buttons will affect content in all the tabs tsuiTabBarbuttons label One type tsprimary label Two type tssecondary label Three tsuiTabBarbuttons label One type tsprimary label Two type tssecondary label Three If the buttons affect the selected tab only remember to clear the buttons when a new tab is selected tsuiTabBarbuttonsclear tsuiTabBarbuttonsclear Heres a summary of the buttons collection and button model Inline TabBar TabBars can be positioned anywhere on the page Assign datatsTabBar to a header or nav to initialize it as a TabBar All features are controlled through a JavaScript API You can get a hold of the component using a CSS selector and call any of the methods weve seen applicable to the Main TabBar tsuigetmytabbar tabbar tabbartabs label One label Two label Three tsuigetmytabbar tabbar tabbartabs label One label Two label Three Heres an overview of the inline TabBar component If you find a bug or need a feature Create GitHub Issue"},{"title":"","href":"components/bars/tabs.html","content":""},{"title":"ToolBar","href":"components/bars/toolbar.html","content":"Main ToolBar Besides buttons for contextual actions the ToolBar also features a Search Beware that this API will be replaced be the tsuiHeader in a future release Before we begin we may consider adding a descriptive title to the ToolBar tsuiToolBartitleMy ToolBar tsuiToolBartitleMy ToolBar ToolBarbuttons Add buttons to the ToolBar with the buttons method This both sets and gets If you omit the argument youll get the current buttons jQuery style tsuiToolBarbuttons label Primary type tsprimary label Secondary type tssecondary label Tertiary One label Tertiary Two tsuiToolBarbuttons label Primary type tsprimary label Secondary type tssecondary label Tertiary One label Tertiary Two You can use array methods like push pop shift unshift splice reverse and so on to manage buttons Just note that the buttons length is readonly The buttons type property works like the CSS class for a regular Button The ToolBar will automatically sort all buttons from primary to tertiary If theres more than one tertiary button these will be pushed to an Aside In the mobile breakpoint all the buttons will be pushed to an Aside Buttons wont actually do anything unless you define the onclick method tsuiToolBarbuttonssplice0 1 label Click me type tsprimary onclick function thislabel Thanks tsuiToolBarbuttonssplice0 1 label Click me type tsprimary onclick function thislabel Thanks Fortunately you can always change what happens when a button gets clicked tsuiToolBarbuttonsforEachfunctionbutton index buttonlabel Button index 1 buttononclick function tsuiNotificationsuccessthislabel tsuiToolBarbuttonsforEachfunctionbutton index buttonlabel Button index 1 buttononclick function tsuiNotificationsuccessthislabel Query buttons You can locate buttons by index in the buttons collection But since this isnt likely to match the order in which they appear on screen its easier to give the buttons an id and find them using buttonsget var buttons tsuiToolBarbuttons buttonspush id examplebutton var button buttonsgetexamplebutton buttonlabel My Button buttontype tssecondary var buttons tsuiToolBarbuttons buttonspush id examplebutton var button buttonsgetexamplebutton buttonlabel My Button buttontype tssecondary Hide buttons You can hide and show buttons You can also toggle visible tsuiToolBarbuttonsforEachfunctionbutton ifbuttonvisible buttonhide else buttonshow tsuiToolBarbuttonsforEachfunctionbutton ifbuttonvisible buttonhide else buttonshow Disable buttons You can disable and enable buttons You can also toggle disabled tsuiToolBarbuttonsforEachfunctionbutton ifbuttondisabled buttonenable else buttondisable tsuiToolBarbuttonsforEachfunctionbutton ifbuttondisabled buttonenable else buttondisable Busy buttons We can display a temporary progress indicator with the busy and done methods var button tsuiToolBarbuttons0 buttonbusy setTimeoutfunction buttondone 1000 var button tsuiToolBarbuttons0 buttonbusy setTimeoutfunction buttondone 1000 The busy method supports an optional status message var button tsuiToolBarbuttons0 buttonbusyMaking progress setTimeoutfunction buttondone 1000 var button tsuiToolBarbuttons0 buttonbusyMaking progress setTimeoutfunction buttondone 1000 Button groups You can also group buttons in arrays to create button groups that look like this tsuiToolBarbuttons label Normal label Normal label Accept type tsprimary label Reject type tsdanger tsuiToolBarbuttons label Normal label Normal label Accept type tsprimary label Reject type tsdanger You can of course also create grouped buttons with icons instead of text var group tsuiToolBarbuttons2 grouppush icon tsiconother type tssecondary var group tsuiToolBarbuttons2 grouppush icon tsiconother type tssecondary Heres a summary of the buttons collection and button model ToolBarsearch Youll get a dedicated search field by passing an object to the search method tsuiToolBarsearch onsearch functionvalue tsuiNotificationsuccessvalue Search cleared tsuiToolBarsearch onsearch functionvalue tsuiNotificationsuccessvalue Search cleared The search field expands when the field is focused by the user or whenever theres a nonempty value in the field You can change the value like this var search tsuiToolBarsearch searchvalue Hello world var search tsuiToolBarsearch searchvalue Hello world Search callbacks The onsearch callback gets invoked when when the user presses ENTER var search tsuiToolBarsearch searchvalue Press ENTER here searchonsearch functionvalue tsuiNotificationsuccessvalue Search cleared var search tsuiToolBarsearch searchvalue Press ENTER here searchonsearch functionvalue tsuiNotificationsuccessvalue Search cleared If defined the onidle method gets called whenever the user pauses typing var search tsuiToolBarsearch searchvalue Try it now searchonidle functionvalue tsuiNotificationsuccessvalue var search tsuiToolBarsearch searchvalue Try it now searchonidle functionvalue tsuiNotificationsuccessvalue The onidle method may also be called when the field loses focus The idletime property controls the timeout value default is 500 milliseconds Search info The info property doubles as both the placeholder when the field is expanded and the title or tooltip when the field is collapsed var search tsuiToolBarsearch searchinfo Search amongst the things searchvalue collapse the field var search tsuiToolBarsearch searchinfo Search amongst the things searchvalue collapse the field Search flex You can flex the search field to make it stretch the available width of the ToolBar In that case it will remain expanded even when theres no default value tsuiToolBarsearch tip Flex all the way flex 1 buttons label No Flex type tsprimary tsuiToolBarsearch tip Flex all the way flex 1 buttons label No Flex type tsprimary You can also assign flex to buttons although that has little practical value In the future we may provide a more advanced distribution scheme Thats why we use a number instead of a boolean but you should always use 1 for now Here an overview of the properties and methods of the Search model and heres a final overview of the Main ToolBar methods Inline ToolBar ToolBars can be positioned anywhere on the page Assign datatsToolBar to a header or menu to initialize it as a ToolBar Another attribute datatstitle assigns a default title to the ToolBar The ToolBar has no default outline so weve fitted ours with a dropshadow In your app any such outlining should be done under consideration of the neighboring elements You can get a hold of the component using a CSS selector and call any of the methods weve seen applicable to the Main ToolBar tsuigetmytoolbar toolbar toolbarbuttons label One type tsprimary label Two type tssecondary label Three tsuigetmytoolbar toolbar toolbarbuttons label One type tsprimary label Two type tssecondary label Three The micro method may come in handy to make the ToolBar somewhat smaller In the HTML you can also assign the CSS classname tsmicro for the same effect tsuigetmytoolbarmicro tsuigetmytoolbarmicro The ToolBar will economize horizonatal space by collecting multiple tertiaray buttons in a menu when you Run This Code you may need to scroll the page back up to see it tsuigetmytoolbar toolbar toolbarbuttonspush label Four label Five label Six tsuigetmytoolbar toolbar toolbarbuttonspush label Four label Five label Six If you are absolutely certain that your buttons will fit in all supported languages you can disable this behavior with the uncompact method tsuigetmytoolbaruncompact tsuigetmytoolbaruncompact Heres an overview of the inline ToolBar component If you find a bug or need a feature Create GitHub Issue"},{"title":"TopBar","href":"components/bars/topbar.html","content":"TopBar Provides tabs for navigation and buttons for contextual actions Beware that this API will be replaced be the tsuiHeader in a future release If you plan to make use of the TopBar we suggest that you give it a descriptive title tsuiTopBartitleMy App tsuiTopBartitleMy App because even when the title is hidden by the tabs like on this page it will become visible when you resize to mobile breakpoint The title also functions to show the TopBar on page load so that it doesnt suddenly appear when you add buttons later TopBartabs We can initialize the TopBar tabs with the the tabs method tsuiTopBartabs label Overview label TopBar label TabBar label ToolBar label StatusBar but since the page already has tabs we will instead append a new tab to the existing collection If you omit the argument youll get the current tabs jQuery style var tabs tsuiTopBartabs tabspush label Bonus Tab onselect function var text thislabel selected tsuiNotificationsuccesstext var tabs tsuiTopBartabs tabspush label Bonus Tab onselect function var text thislabel selected tsuiNotificationsuccesstext You can use array methods like push pop shift unshift splice and so on to manage tabs just note that the tabs length is a readonly property Also note that tabs dont do anything by default so what happens at onselect is completely up to you Updating tabs We can at any time change what happens when a tab gets selected We can also change the tab label if we like although maybe this would be confusing for the user var tabs tsuiTopBartabs tabs4label Choose Me tabs4onselect function thislabel Thanks var tabs tsuiTopBartabs tabs4label Choose Me tabs4onselect function thislabel Thanks Selecting tabs We can programatically select a tab using one of these approaches tsuiTopBartabs4select tsuiTopBartabsselectedIndex 1 Querying tabs This will all become a lot easier if we give all the tabs an id and use tabsget var tabs tsuiTopBartabs tabssplice4 0 label Example Tab id exampletab tabsgetexampletabselect var tabs tsuiTopBartabs tabssplice4 0 label Example Tab id exampletab tabsgetexampletabselect Tabs icons You can add a tab with an icon if somehow that tab is special tsuiTopBartabspush label Icon Tab icon tsicontodo tsuiTopBartabspush label Icon Tab icon tsicontodo Tab counters You can add a counter to the tabs for whatever reason you like tsuiTopBartabsforEachfunctiontab tabcounter MathceilMathrandom 10 tsuiTopBartabsforEachfunctiontab tabcounter MathceilMathrandom 10 When the counter reaches zero it disappears tsuiTopBartabsforEachfunctiontab tabcounter tsuiTopBartabsforEachfunctiontab tabcounter Closeable tabs You can create closeable tabs but note that the tab must be selected before it can be closed You can return false in the onclose method to prevent the tab from closing if this would otherwise cause data loss tsuiTopBartabspush label Closeable Tab closeable true selected true onclose function tsuiNotificationsuccessthislabel closed tsuiTopBartabspush label Closeable Tab closeable true selected true onclose function tsuiNotificationsuccessthislabel closed NewTab button You can allow the user to create new tabs via a special button as seen in popular browsers Note that the button just triggers a callback and that the new tab must be created manually In the example below the selected property also selects the tab var tabs tsuiTopBartabs tabsshowNewfunction onclick tabspush label My New Tab selected true var tabs tsuiTopBartabs tabsshowNewfunction onclick tabspush label My New Tab selected true If you regret this later on you can also hide the button tsuiTopBartabshideNew tsuiTopBartabshideNew Heres a summary of the tabs collection and tab model TopBarbuttons Add buttons to the TopBar with the buttons method This both sets and gets If you omit the argument youll get the current buttons jQuery style tsuiTopBarbuttons label Primary type tsprimary label Secondary type tssecondary label Tertiary One label Tertiary Two tsuiTopBarbuttons label Primary type tsprimary label Secondary type tssecondary label Tertiary One label Tertiary Two You can use array methods like push pop shift unshift splice reverse and so on to manage buttons Just note that the buttons length is readonly The buttons type property works like the CSS class for a regular Button The TopBar will automatically sort all buttons from primary to tertiary If theres more than one tertiary button these will be pushed to an Aside In the mobile breakpoint all the buttons will be pushed to an Aside Buttons wont actually do anything unless you define the onclick method tsuiTopBarbuttonssplice0 1 label Click me type tsprimary onclick function thislabel Thanks tsuiTopBarbuttonssplice0 1 label Click me type tsprimary onclick function thislabel Thanks Fortunately you can always change what happens when a button gets clicked tsuiTopBarbuttonsforEachfunctionbutton index buttonlabel Button index 1 buttononclick function tsuiNotificationsuccessthislabel tsuiTopBarbuttonsforEachfunctionbutton index buttonlabel Button index 1 buttononclick function tsuiNotificationsuccessthislabel Query buttons You can locate buttons by index in the buttons collection But since this isnt likely to match the order in which they appear on screen its easier to give the buttons an id and find them using buttonsget var buttons tsuiTopBarbuttons buttonspush id examplebutton var button buttonsgetexamplebutton buttonlabel My Button buttontype tssecondary var buttons tsuiTopBarbuttons buttonspush id examplebutton var button buttonsgetexamplebutton buttonlabel My Button buttontype tssecondary Hide buttons You can hide and show buttons You can also toggle visible tsuiTopBarbuttonsforEachfunctionbutton ifbuttonvisible buttonhide else buttonshow tsuiTopBarbuttonsforEachfunctionbutton ifbuttonvisible buttonhide else buttonshow Disable buttons You can disable and enable buttons You can also toggle disabled tsuiTopBarbuttonsforEachfunctionbutton ifbuttondisabled buttonenable else buttondisable tsuiTopBarbuttonsforEachfunctionbutton ifbuttondisabled buttonenable else buttondisable Busy buttons We can display a temporary progress indicator with the busy and done methods var button tsuiTopBarbuttons0 buttonbusy setTimeoutfunction buttondone 1000 var button tsuiTopBarbuttons0 buttonbusy setTimeoutfunction buttondone 1000 The busy method supports an optional status message var button tsuiTopBarbuttons0 buttonbusyMaking progress setTimeoutfunction buttondone 1000 var button tsuiTopBarbuttons0 buttonbusyMaking progress setTimeoutfunction buttondone 1000 Button groups You can also group buttons in arrays to create button groups that look like this tsuiTopBarbuttons label Normal label Normal label Accept type tsprimary label Reject type tsdanger tsuiTopBarbuttons label Normal label Normal label Accept type tsprimary label Reject type tsdanger You can of course also create grouped buttons with icons instead of text var group tsuiTopBarbuttons2 grouppush icon tsiconother type tssecondary var group tsuiTopBarbuttons2 grouppush icon tsiconother type tssecondary Heres a summary of the buttons collection and button model TopBar Back Forward The TopBar features both Back and Forward buttons for use in drill down scenarios tsuiTopBarshowBackfunction consolelogBack showNextfunction consolelogNext tsuiTopBarshowBackfunction consolelogBack showNextfunction consolelogNext You can also hide the Back and Forward buttons Since the buttons obscure the tabs you might actually like to do that now tsuiTopBarhideBackhideNext tsuiTopBarhideBackhideNext Note that tabbed navigation is not supposed to coexist with Back and Forward buttons Hide show the TopBar You can hide the TopBar but not in mobile breakpoint see below Note that this operation will clear the contents of the TopBar tsuiTopBarhide tsuiTopBarhide You can also show it again Because the content was cleared well also restore it tsuiTopBarshow restoreTopBar tsuiTopBarshow restoreTopBar When you resize the window to mobile breakpoint the hidden TopBar will be shown again automatically Thats because the TopBar is used to access the main navigation Without the TopBar you would be stuck in the app forever But since you chose to hide the TopBar we can assume that the content of the TopBar is not relevant Therefore Since we dont want to show an outdated TopBar to mobile users the content of the TopBar will be cleared when you hide it To restore the old content you will simply have to populate the TopBar again If you dont want your app to feature a TopBar under any circumstance you can simply remove the whole from the HTML TopBar summary Heres a summary of the TopBar methods including some bonus not yet discussed If you find a bug or need a feature Create GitHub Issue"},{"title":"Buttons","href":"components/buttons/buttons.html","content":"Buttons Group buttons in menus to unlock advanced layout options Assign datatsButtons attribute to a menu to initialize it as a Buttons menu Button One Button Two Button One Button Two When in menus buttons stack vertically and stretch to fill the width You can omit the tsbutton attribute on buttons it is implied You can also omit the tstertiary classname on the buttons it is assumed by default Button layouts The menu can be assigned a classname to layout the buttons horizontally Accept Reject Accept Reject The classname tstt indicates that two buttons should both display text instead of icons If you add both the layout will take care of hiding one or the other A special classname tsjoin has been added to join the buttons together We support the following permutations edbmldeclareedbmlklDUi2asfunction edbml use strict var out edbmlout txt edbmlsafetext val edbmlsafeattr tstt tsit tsti tsiit tsiti tstii mapfunctionc rendermenuc return c forEachfunctionc rendermenuc tsjoin function rendermenuc1 c2 var cname c1 c2 outhtml c1substringtslengthsplitforEachfunction outhtml txtcname outhtml return outwrite The classname shown on buttons should in all cases go on the menu element and not on the button elements If you find a bug or need a feature Create GitHub Issue"},null,{"title":"Button Gallery","href":"components/buttons/gallery.html","content":"Button Gallery function togglekey checkbox var menu documentquerySelector key var buttons menuquerySelectorAllbutton guiArrayfrombuttonsforEachfunctionb bdisabled bdisabled tsdoxtabs edbmldeclareedbmlZsJn2z1asfunction edbml use strict var out edbmlout att edbmlatt txt edbmlsafetext val edbmlsafeattr layout edbmlinputtsuiLayoutModel var spirit this var backgroundcolors tsbglite tsbgwhite tsbgyellow tsbgdark tsbgblue tsbgred tsbgorange tsbggreen tsbgpurple var buttonlabeltexts Primary Secondary Tertiary var buttonclassnames tsprimary tssecondary tstertiary rendercolumnslayoutbreakpoint desktop function rendercolumnsdesktop if desktop outhtml backgroundcolorsforEachfunctionclassname outhtml txtclassname outhtml backgroundcolorsforEachfunctionclassname outhtml renderbuttons outhtml outhtml else backgroundcolorsforEachfunctionclassname outhtml renderbuttons outhtml function renderbuttons var key guiKeyMastergenerateKey outhtml buttonclassnamesforEachfunctionclassname i outhtml attdisabled spiritdisabled disabled null outhtml txtbuttonlabeltextsi outhtml renderTogglekey function rendernested outhtml Nested tsbgwhite buttonclassnamesforEachfunctionclassname i outhtml outhtml function renderTogglekey outhtml Disabled return outwrite withInstructions input name layout type tsuiLayoutModel "},null,{"title":"Button","href":"components/buttons/index.html","content":"Button Use button classnames to prioritize the possible actions in your app Assign datatsButton to a button to initialize it as a Button Default Button Default Button The default button looks like a link but some CSS classnames can be added to make it look more like a button Primary Secondary Tertiary Primary Secondary Tertiary Button icons Icons go into a separate i element You can see a list of all icons Button Text Button Text Youll notice in the code snippet that the span has been set to displaynone Buttons should never show both text and icon at the same time If you need both its up to you to hide one or the other In this example the button has been rigged up to show the icon only in the mobile breakpoint Hidden In Mobile Hidden In Mobile Button spinner Assign the datatsbusy attribute to a button to initialize a spinner Primary show spinner Micro Button You can add class tsmicro to get a micro button Primary Secondary Tertiary Primary Secondary Tertiary You can group buttons in menus to unlock advanced layout options If you find a bug or need a feature Create GitHub Issue"},{"title":"","href":"components/buttons/tabs.html","content":""},null,null,null,null,null,{"title":"CompanyCard","href":"components/cards/companycard.html","content":"CompanyCard tsdoxtabs CompanyCard In this first iteration the CompanyCard is simply a HTML rendering that you can feed with JSON in various ways You can initialize a CompanyCard with the attribute datatsCompanyCard Even without any data the card takes on a cardlike appearance If you are using Angular or jQuery you might like to feed the card through a JavaScript API as we will see you can however also embed the data directly in the markup Embedded JSON Serverside devs and UX designers might like to embed the JSON in the HTML Because this is JSON you should use double quotes and omit trailing commas id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Tradeshift logo assetslogopng size 100249 location San Francisco California industry Software IT connection 2 id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Tradeshift logo assetslogopng size 100249 location San Francisco California industry Software IT connection 2 Encoded JSON You can also embed the JSON in an attribute datatsrender The JSON string must be encoded in the format returned by method encodeURIComponentjson Remember to trim the JSON string before you encode it Render programatically You can grab a hold of the card and instruct it to render some JSON data tsuigetmycard card cardrender id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Tradeshift logo assetslogopng size 100249 location San Francisco California industry Software IT connection 2 tsuigetmycard card cardrender id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Tradeshift logo assetslogopng size 100249 location San Francisco California industry Software IT connection 2 We notice that the connection status is indicated by a number The number matches an index in the following array which declares the label and icon tsuiCompanyCardconnectionTypes Your company tsiconnetwork Request sent tsiconnetwork Connected tsiconnetwork Registration in progress tsiconnetwork In your Google Contacts tsiconnetwork Via email only tsiconnetwork This array is crowdsourced You can modify the array in your app simply by copypasting the code above into your initialization script You can also use numbers instead of strings to indicate size and industry cardrender id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Tradeshift size 3 industry 6 If you provide a number instead of a string well look it up in these lists tsuiCompanyCardcompanySizes 1 110 1100 100249 250500 5001000 tsuiCompanyCardindustryTypes Airline Corporation Educational Organization Government Organization Local Business NGO Software IT Performing Group Sports Team You are also welcome to overwrite these arrays in your app Thats it for now"},{"title":"CompanyCard extras","href":"components/cards/extras.html","content":"CompanyCard extras These are considered experimental features You can feed data to your cards without poking around in the DOM In your HTML you must declare your cards with a datatsid attribute assigned You can now or even before import the JSON from a demo file and instruct the cards to render getJSONassetscardsjson functionjson tsuiCompanyCardrenderjson The details view The card should eventually be able to render its own details view so that it looks the same outside of V4 Theres a lot of infrastructure that needs to happen first not least with translations in the Runtime but it could look like this tsuigetmycardopen tsuigetmycardopen If you find a bug or need a feature Create GitHub Issue"},{"title":"","href":"components/cards/tabs.html","content":""},{"title":"UserCard","href":"components/cards/usercard.html","content":"UserCard figure output textalign center tsdoxtabs UserCard In this first iteration the UserCard can simply show some user details in an Aside The properties are all optional but you should at least include the name tsuiUserCard id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Wired Earp image assetswiredearppng title EDB Programmer role Gentleman Spy email jmotradeshiftcom company Tradeshift companyUrl httptradeshiftcom open tsuiUserCard id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Wired Earp image assetswiredearppng title EDB Programmer role Gentleman Spy email jmotradeshiftcom company Tradeshift companyUrl httptradeshiftcom open"},{"title":"DatePicker","href":"components/datepicker/index.html","content":"DatePicker Calendar widget that appears in Aside Used in Forms for an implementation of elements The DatePicker can be launched with a JavaScript API You should implement the onselect method to get notified whenever the user picks a date Note that you must manually open and close the DatePicker var datePicker tsuiDatePicker title Your Birthday value 19730326 onselect functionnewval oldval tsuiNotificationsuccessthisvalue thisclose onclosed function thisdispose datePickeropen var datePicker tsuiDatePicker title Your Birthday value 19730326 onselect functionnewval oldval tsuiNotificationsuccessthisvalue thisclose onclosed function thisdispose datePickeropen You can specify a min and max value tsuiDatePicker title Your Birthday value 19840523 min 19840101 max 19851224 onselect function thisclose onclosed function thisdispose open tsuiDatePicker title Your Birthday value 19840523 min 19840101 max 19851224 onselect function thisclose onclosed function thisdispose open The object argument configures a tsuiDatePickerModel as outlined below tsuiDatePickerModel Instance properties title string Appears as the title of the DatePicker value string The selected date Must be dashseparated ISO 8601 formatted date string eg 20150101 Instance methods open void Open the DatePicker close void Close the DatePicker onselect void Called whenever selection changes with two arguments newval and oldval onclosed void Event listener for close event Called after aside closing animation is completed dispose void Cleanup the DataPicker recommended If you find a bug or need a feature Create GitHub Issue"},{"title":"Dialog","href":"components/dialogs/index.html","content":"Dialog The Dialog API can be used to ask simple questions much like the JavaScript confirm method You can launch a Dialog with methods to handle OK and Cancel tsuiDialogconfirmWill you try onaccept function tsuiNotificationsuccessGood luck oncancel function tsuiNotificationsuccessCome back later tsuiDialogconfirmWill you try onaccept function tsuiNotificationsuccessGood luck oncancel function tsuiNotificationsuccessCome back later You are encouraged to specify the text of the OK button The button should attempt to indicate what happens when you press it tsuiDialogconfirmShow the Notification Show It onaccept function tsuiNotificationsuccessGood choice tsuiDialogconfirmShow the Notification Show It onaccept function tsuiNotificationsuccessGood choice You can add a third string argument to specify the Cancel text Buttons setup Dialog buttons are secondary blue by default but you can choose to make the accept or cancel button primary You can also tweak the default focus tsuiDialogconfirmSign up for Tradeshift Join Now primary accept focused accept tsuiDialogconfirmSign up for Tradeshift Join Now primary accept focused accept You can change the label of both the primary and secondary buttons tsuiDialogconfirmSign up for Tradeshift Join Now Not Now primary accept focused accept tsuiDialogconfirmSign up for Tradeshift Join Now Not Now primary accept focused accept Warning dialogs You can launch special dialogs to confirm choices of more dire consequence tsuiDialogwarningThis will delete the thing Delete It onaccept function tsuiDialogdanger Are you absolutely sure you want to permanently delete the whole thing Delete It tsuiDialogwarningThis will delete the thing Delete It onaccept function tsuiDialogdanger Are you absolutely sure you want to permanently delete the whole thing Delete It Dialog icons You can point the icon property to an alternative icon class but you should stick to the stock icons whenever possible so that the user can easily recognize the dialog type tsuiDialogconfirmProceed to Checkout Check Out icon tsiconcart primary accept focused accept tsuiDialogconfirmProceed to Checkout Check Out icon tsiconcart primary accept focused accept If you find a bug or need a feature Create GitHub Issue"},{"title":"Footer Actions","href":"components/footer/actions.html","content":"Footer actions Footer actions can be used to manipulate selected objects of any kind They appear in a separate toolbar so that they never conflict with the normal buttons This toolbar can also be configured with a status message and this checkbox The actions method both sets and gets the actions If you omit the argument youll get the current actions jQuery style In real life the actions should only appear whenever the user has selected something with the mouse or keyboard so we will just have to pretend that something is selected tsuiFooteractions label Move Up icon tsicontriangleup label Move Down icon tsicontriangledown label Move Left icon tsicontriangleleft label Move Right icon tsicontriangleright label Dont Move icon tsiconhalt onclick tsuiFooteractionsclear tsuiFooteractions label Move Up icon tsicontriangleup label Move Down icon tsicontriangledown label Move Left icon tsicontriangleleft label Move Right icon tsicontriangleright label Dont Move icon tsiconhalt onclick tsuiFooteractionsclear You can use array methods like push pop shift unshift splice and so on to manage actions just note that the actions length is a readonly property To ensure consistency actions should always have both an icon and a label much unlike the buttons Hide actions You can hide and show actions You can also toggle visible tsuiFooteractionsforEachfunctionaction ifactionvisible actionhide else actionshow tsuiFooteractionsforEachfunctionaction ifactionvisible actionhide else actionshow Disable actions You can disable and enable action You can also toggle disabled tsuiFooteractionsforEachfunctionaction ifactiondisabled actionenable else actiondisable tsuiFooteractionsforEachfunctionaction ifactiondisabled actionenable else actiondisable Busy actions We can display a temporary progress indicator with the busy and done methods var action tsuiFooteractions0 actionbusy setTimeoutfunction actiondone 1000 var action tsuiFooteractions0 actionbusy setTimeoutfunction actiondone 1000 The busy method supports an optional message var action tsuiFooteractions0 actionbusyMaking progress setTimeoutfunction actiondone 1000 var action tsuiFooteractions0 actionbusyMaking progress setTimeoutfunction actiondone 1000 Heres a summary of the actions collection and action model Status message We can configure the actionbar with a status message When a selection is made the massage could be something like 23 products selected When nothing is selected it could perhaps be something like Showing 1020 out of 123 products tsuiFooterstatus23 of one million products selected tsuiFooterstatus23 of one million products selected If you call linkable you can also some links in the message Beware of phishing tsuiStatusBarlinkablemessage Please visit Tradeshifthttpwwwtradeshiftcom tsuiStatusBarlinkablemessage Please visit Tradeshifthttpwwwtradeshiftcom You can pass a callback function to be invoked whenever a link is clicked tsuiStatusBarlinkablefunction onclickurl tsuiNotificationsuccessurl thisstatusThanks messagePlease click the linkThe URL can be any string tsuiStatusBarlinkablefunction onclickurl tsuiNotificationsuccessurl thisstatusThanks messagePlease click the linkThe URL can be any string Checkbox Theres also a checkbox which conceptually can be used to manage selections This is the minimum viable implementation tsuiFootercheckbox onclick function thischecked thischecked tsuiFootercheckbox onclick function thischecked thischecked You must manually toggle the checked property This will give you a chance to let the user confirm if he really intends to select millions of products or if he really wants to clear a selection that took him hours to complete Here is the CheckBoxModel Use the indeterminate property if state that is neither checked nor unchecked Its a inbetween state that can be used show a partial selection and to check all selections var i 0 tsuiFootercheckbox onclick function switch i 3 case 0 unchecked thischecked false tsuiFooterstatus0 of 3 items selected break case 1 indeterminate overrides checked thischecked true thisindeterminate true tsuiFooterstatus1 of 3 items selected break case 2 checked thisindeterminate false tsuiFooterstatus3 of 3 items selected break status0 of 3 items selected var i 0 tsuiFootercheckbox onclick function switch i 3 case 0 unchecked thischecked false tsuiFooterstatus0 of 3 items selected break case 1 indeterminate overrides checked thischecked true thisindeterminate true tsuiFooterstatus1 of 3 items selected break case 2 checked thisindeterminate false tsuiFooterstatus3 of 3 items selected break status0 of 3 items selected The example above shows that the indeterminate property will take precedence over the checked property If you find a bug or need a feature Create GitHub Issue"},{"title":"Footer Buttons","href":"components/footer/buttons.html","content":"Footer buttons Add buttons to the Footer with the buttons method This both sets and gets If you omit the argument youll get the current buttons jQuery style tsuiFooterbuttons label Primary type tsprimary label Secondary type tssecondary label Tertiary One label Tertiary Two tsuiFooterbuttons label Primary type tsprimary label Secondary type tssecondary label Tertiary One label Tertiary Two You can use array methods like push pop shift unshift splice reverse and so on to manage buttons Just note that the buttons length is readonly The buttons type property works like the CSS class for a regular Button The Footer will automatically sort all buttons from primary to tertiary If theres more than one tertiary button these will be pushed to an Aside In the mobile breakpoint all the buttons will be pushed to an Aside Buttons wont actually do anything unless you define the onclick method tsuiFooterbuttonssplice0 1 label Click me type tsprimary onclick function thislabel Thanks tsuiFooterbuttonssplice0 1 label Click me type tsprimary onclick function thislabel Thanks Fortunately you can always change what happens when a button gets clicked tsuiFooterbuttonsforEachfunctionbutton index buttonlabel Button index 1 buttononclick function tsuiNotificationsuccessthislabel tsuiFooterbuttonsforEachfunctionbutton index buttonlabel Button index 1 buttononclick function tsuiNotificationsuccessthislabel Query buttons You can locate buttons by index in the buttons collection But since this isnt likely to match the order in which they appear on screen its easier to give the buttons an id and find them using buttonsget var buttons tsuiFooterbuttons buttonspush id examplebutton var button buttonsgetexamplebutton buttonlabel My Button buttontype tssecondary var buttons tsuiFooterbuttons buttonspush id examplebutton var button buttonsgetexamplebutton buttonlabel My Button buttontype tssecondary Hide buttons You can hide and show buttons You can also toggle visible tsuiFooterbuttonsforEachfunctionbutton ifbuttonvisible buttonhide else buttonshow tsuiFooterbuttonsforEachfunctionbutton ifbuttonvisible buttonhide else buttonshow Disable buttons You can disable and enable buttons You can also toggle disabled tsuiFooterbuttonsforEachfunctionbutton ifbuttondisabled buttonenable else buttondisable tsuiFooterbuttonsforEachfunctionbutton ifbuttondisabled buttonenable else buttondisable Busy buttons We can display a temporary progress indicator with the busy and done methods var button tsuiFooterbuttons0 buttonbusy setTimeoutfunction buttondone 1000 var button tsuiFooterbuttons0 buttonbusy setTimeoutfunction buttondone 1000 The busy method supports an optional status message var button tsuiFooterbuttons0 buttonbusyMaking progress setTimeoutfunction buttondone 1000 var button tsuiFooterbuttons0 buttonbusyMaking progress setTimeoutfunction buttondone 1000 Button groups You can also group buttons in arrays to create button groups that look like this tsuiFooterbuttons label Normal label Normal label Accept type tsprimary label Reject type tsdanger tsuiFooterbuttons label Normal label Normal label Accept type tsprimary label Reject type tsdanger You can of course also create grouped buttons with icons instead of text var group tsuiFooterbuttons2 grouppush icon tsiconother type tssecondary var group tsuiFooterbuttons2 grouppush icon tsiconother type tssecondary Heres a summary of the buttons collection and button model If you find a bug or need a feature Create GitHub Issue"},{"title":"Footer Collaboration","href":"components/footer/collabbutton.html","content":"Footer collabbutton The Footer features a special button which is dedicated to launching the collaboration panel To show the button simply call the method configbutton with a callback tsuiFootercollabbuttonfunction onclick tsuiNotificationsuccessGo collaborate tsuiFootercollabbuttonfunction onclick tsuiNotificationsuccessGo collaborate Note that the Footer doesnt automatically initialize or resume the collbaroration The API for this will be provided elsewhere You can hide the collaboration button by passing null to the same method tsuiFootercollabbuttonnull tsuiFootercollabbuttonnull If you find a bug or need a feature Create GitHub Issue"},{"title":"Footer Configuration","href":"components/footer/configbutton.html","content":"Footer configbutton There Footer can be fitted with a special button for the purpose of configuring things To show the button simply call the method configbutton with a callback tsuiFooterconfigbuttonfunction onclick tsuiNotificationsuccessGo configure tsuiFooterconfigbuttonfunction onclick tsuiNotificationsuccessGo configure What happens when you click the button is completely up to you Fortunately you can also hide the button again by passing null to the same method tsuiFooterconfigbuttonnull tsuiFooterconfigbuttonnull If you find a bug or need a feature Create GitHub Issue"},{"title":"Footer Gallery","href":"components/footer/gallery.html","content":"Footer gallery Here you can test how the Footer behaves when you enable all the features 1 Add a pager tsuiFooterpager pages 23 page 0 onselect functionindex consolelogindex tsuiFooterpager pages 23 page 0 onselect functionindex consolelogindex 2 Add some buttons tsuiFooterbuttons label Button 1 type tsprimary label Button 2 type tssecondary label Button 3 label Button 4 label Button 5 tsuiFooterbuttons label Button 1 type tsprimary label Button 2 type tssecondary label Button 3 label Button 4 label Button 5 3 Add more buttons until they crash into the Pager Behold the second toolbar tsuiFooterbuttonssplice2 0 label Bonus Button type tssecondary tsuiFooterbuttonssplice2 0 label Bonus Button type tssecondary 4 The actions will appear in yet another toolbar Thats right tsuiFooteractions label Move Up icon tsicontriangleup label Move Down icon tsicontriangledown label Move Left icon tsicontriangleleft label Move Right icon tsicontriangleright label Dont Move icon tsiconhalt statusSomething is selectedcheckbox onclick function thischecked thischecked tsuiFooteractions label Move Up icon tsicontriangleup label Move Down icon tsicontriangledown label Move Left icon tsicontriangleleft label Move Right icon tsicontriangleright label Dont Move icon tsiconhalt statusSomething is selectedcheckbox onclick function thischecked thischecked 5 Finally add the configuration and collaboration buttons tsuiFooterconfigbuttonfunction onclick tsuiNotificationsuccessGo configure collabbuttonfunction onclick tsuiNotificationsuccessGo collaborate tsuiFooterconfigbuttonfunction onclick tsuiNotificationsuccessGo configure collabbuttonfunction onclick tsuiNotificationsuccessGo collaborate With the Footer fully equipped we can try to hide and destroy these things again Hide something or everything If you need to temporarily hide a single Footer member you can call the associated method without any arguments to get a hold of the thing and then call the hide and show methods You can also toggle the visible property var thing pause action setTimeoutaction 500 function togglethings ifthingslength ifthing thingsshift thinghide pause thingshow pause togglethings else togglethings tsuiFooterbuttons tsuiFooteractions tsuiFooterpager tsuiFootercheckbox tsuiFootercollabbutton tsuiFooterconfigbutton var thing pause action setTimeoutaction 500 function togglethings ifthingslength ifthing thingsshift thinghide pause thingshow pause togglethings else togglethings tsuiFooterbuttons tsuiFooteractions tsuiFooterpager tsuiFootercheckbox tsuiFootercollabbutton tsuiFooterconfigbutton Remember that the hidden thing remains hidden until you show it again You can of course also show and hide the whole Footer Again note that it will remain hidden tsuiFooterhide setTimeout tsuiFootershow 500 tsuiFooterhide setTimeout tsuiFootershow 500 Clear something or everything If you are sure that you wont need to show a configured Footer member again at some point in the future it is advised that you completely destroy it instead of just hide it You can do this by passing null to the associated method function destructiveactions actionsshift ifactionslength setTimeout destructiveactions 500 tsuiFooterpagernull tsuiFooterstatusnull tsuiFootercheckboxnull tsuiFooterbuttonsnull tsuiFooteractionsnull tsuiFootercollabbuttonnull tsuiFooterconfigbuttonnull function destructiveactions actionsshift ifactionslength setTimeout destructiveactions 500 tsuiFooterpagernull tsuiFooterstatusnull tsuiFootercheckboxnull tsuiFooterbuttonsnull tsuiFooteractionsnull tsuiFootercollabbuttonnull tsuiFooterconfigbuttonnull You can of course also just clear everything and the Footer will automatically hide tsuiFooterclear tsuiFooterclear If you find a bug or need a feature Create GitHub Issue"},{"title":"Footer Pager","href":"components/footer/index.html","content":"Footer This is a developer preview All features can be expected to change The Footer appears near the bottom of the page where it is commonly used to display some buttons All features are controlled with an API that looks something like this tsuiFooterbuttons label Continue type tsprimary onclick function toplocationhash componentsfooterbuttonshtml tsuiFooterbuttons label Continue type tsprimary onclick function toplocationhash componentsfooterbuttonshtml Heres a quick overview of the Footer API You can read more in the following pages If you find a bug or need a feature Create GitHub Issue"},{"title":"Footer Pager","href":"components/footer/pager.html","content":"Footer pager The Footer features a Pager The pager method both sets and gets the Pager If you omit the argument youll get the current Pager jQuery style You can pass null to the method to destroy the Pager once you are done with it tsuiFooterpager pages 23 page 0 onselect functionindex consolelogindex tsuiFooterpager pages 23 page 0 onselect functionindex consolelogindex If you need to update the index later on for example to support history navigation it is recommended that you change the page property of the existing Pager instead of initializing a whole new Pager You can just call the same method without arguments tsuiFooterpagerpage 23 If you find a bug or need a feature Create GitHub Issue"},{"title":"","href":"components/footer/tabs.html","content":""},null,{"title":"Form Autocomplete","href":"components/forms/autocomplete.html","content":"Form Autocomplete tsdoxtabs Autocomplete You can have an input field suggest results to the user and can be navigated using the keyboard or the mouse Basic Usage Loading the autocomplete data from a static array tsuigetmystaticautocomplete autocomplete autocompletedata key 0 value zero key 1 value one key 2 value two key 3 value three key 4 value four key 5 value five key 6 value six key 7 value seven key 8 value eight key 9 value nine tsuigetmystaticautocomplete autocomplete autocompletedata key 0 value zero key 1 value one key 2 value two key 3 value three key 4 value four key 5 value five key 6 value six key 7 value seven key 8 value eight key 9 value nine Autocomplete from array External Data Loading all results from an external JSON endpoint but using the built in filtering tsuigetmyadvancedautocomplete autocomplete getJSONassetsautocompletejson functionjson autocompletedatajson tsuigetmyadvancedautocomplete autocomplete getJSONassetsautocompletejson functionjson autocompletedatajson Autocomplete from JSON Advanced Usage Its possible to override the filtering functionality to supply the user with any data youd like tsuigetmyfancyautocomplete autocomplete autocompleteonfilterfunctionfilter var output for var i parseIntMathrandom 10 1 10 i 0 i outputpush key i value MathrandomtoString36substr2 5 return output tsuigetmyfancyautocomplete autocomplete autocompleteonfilterfunctionfilter var output for var i parseIntMathrandom 10 1 10 i 0 i outputpush key i value MathrandomtoString36substr2 5 return output Autocomplete with custom results Overriding onselect onselect can be overridden to run your own code when an element is selected either with the keyboard or the mouse tsuigetmyspecialautocomplete autocomplete autocompletedata key 0 value zero key 1 value one autocompleteonselectfunctionitem tsuiNotificationsuccess itemvalue selected return itemvalue tsuigetmyspecialautocomplete autocomplete autocompletedata key 0 value zero key 1 value one autocompleteonselectfunctionitem tsuiNotificationsuccess itemvalue selected return itemvalue Autocomplete with special onselect"},{"title":"Custom Select","href":"components/forms/custom-select.html","content":"Custom Select documentreadyfunction usercontainer divclickfunctione var name ecurrentTargetattrname tsuigetmyAside aside asideclose mySelectvalname tsuiNotificationsuccessname usercontainer div margin 11px cursor pointer tsdoxtabs Custom Select You can handle the onclick action on a select input element to make your own select if you set the attribute datatscustomtrue Following example is custom user select which made step by step 1 Create your own select input element Select Karl Benson Marshall Garrett Natalie Carr Rochelle Cox Mae Schultz Jimmie Edwards Select Karl Benson Marshall Garrett Natalie Carr Rochelle Cox Mae Schultz Jimmie Edwards 2 Create your own Aside and fill up options in the panel of the Aside Karl Benson Marshall Garrett Natalie Carr Rochelle Cox Mae Schultz Jimmie Edwards Karl Benson Marshall Garrett Natalie Carr Rochelle Cox Mae Schultz Jimmie Edwards 3 Handle the onClick event of the options documentreadyfunction usercontainer divclickfunctione var name ecurrentTargetattrname tsuigetmyAside aside asideclose mySelectvalname tsuiNotificationsuccessname documentreadyfunction usercontainer divclickfunctione var name ecurrentTargetattrname tsuigetmyAside aside asideclose mySelectvalname tsuiNotificationsuccessname 4 You can run the following code first mySelectclickfunction tsuigetmyAside aside asideopen mySelectclickfunction tsuigetmyAside aside asideopen 5 Click the select below to check how it works Good luck Select Karl Benson Marshall Garrett Natalie Carr Rochelle Cox Mae Schultz Jimmie Edwards Karl Benson Marshall Garrett Natalie Carr Rochelle Cox Mae Schultz Jimmie Edwards"},{"title":"Disabled & Readonly Fields","href":"components/forms/disabled.html","content":"Disabled and readonly fields Form fields can be set to be disabled or readonly the same way you would in XHTML5 You can set datatspreview attribute to preview whole form input typetext disabled Disabled Text Disabled Text input typetext readonly Readonly Text Readonly Text textarea disabled Disabled Textarea Fatback kevin picanha pork loin kielbasa turducken doner Beef ribs tongue ham ball tip hamburger pork loin biltong sausage salami sirloin tenderloin kevin shank pig meatloaf Disabled Textarea Fatback kevin picanha pork loin kielbasa turducken doner Beef ribs tongue ham ball tip hamburger pork loin biltong sausage salami sirloin tenderloin kevin shank pig meatloaf date disabled Disabled Date Disabled Date select disabled Disabled Select One Two Three Four Five Disabled Select One Two Three Four Five input typeradio disabled There is no choice Red pill Blue pill There is no choice Red pill Blue pill input typecheckbox disabled By browsing this page you agree to our terms I agree to something I agree to something by default By browsing this page you agree to our terms I agree to something I agree to something by default input typecheckbox disabled alternate version Its not a bug its a feature Secret Feature Secret Feature On by default Its not a bug its a feature Secret Feature Secret Feature On by default form datatspreviewtrue If you find a bug or need a feature Create GitHub Issue"},{"title":"Form Example","href":"components/forms/example.html","content":"Form Example function Controllerscope scopemodel poref invalid gln 1234567890123 windowangularmoduleapp controllerController scope Controller tsdoxtabs ErrorInfo example Here you can see a full example on how to use the error and info helpers for form fields using AngularJS Text PO line item reference Error PO line item reference Must be 4 numeric digits in length Must be present on the related PO document GLN Optional Definition GLN A GLN Global Location Number is a globally unique 13 digit numeric identifier that is used to access data about a location More information about the GLN System Error GLN Must be 13 numeric digits in length Can only contain numbers Heres the source for the form above Text PO line item reference Error PO line item reference Must be 4 numeric digits in length Must be present on the related PO document GLN Optional Definition GLN A GLN Global Location Number is a globally unique 13 digit numeric identifier that is used to access data about a location More information about the GLN System Error GLN Must be 13 numeric digits in length Can only contain numbers If you find a bug or need a feature Create GitHub Issue"},{"title":"Form","href":"components/forms/index.html","content":"Form Provides styling and behavior for form controls and error messages Assign datatsForm to a form to initialize as a Form Form components depend on specific internal element structure in order to initialize and style their contents Most components adhere to this structure textarea Starts out with three lines but will expand up to ten as content is entered The rows attribute can be used to adjust the initial amount of lines to show Textarea Textarea Textarea You can specify typesubmit to make the texarea submit the form on ENTER In this mode newlines may still be entered while pressing the SHIFT key Press SHIFT to ENTER newlines Press SHIFT to ENTER newlines Press SHIFT to ENTER newlines input typetext Text Text Text input typetel Tel Tel Tel input typeemail Email Email Email input typenumber Set the class classtsright on the label to make your number text align right Number Number Number input typedate Date Date Date select The select will open in an Aside but youll mantain it like a normal select Note that the select only triggers a change event when the Aside is fully closed Set the attribute datatscustomtrue to handle your own select event Select One Two Three Select One Two Three Select One Two Three You can configure the select with a default placeholder in a twostep process Add the placeholder attribute to the select Leave the first option empty no option text Select with placeholder 5 23 Select with placeholder 5 23 Select with placeholder 5 23 When a selection is made the user can revert to the default no selection by clicking the selected option a second time If you dont want to allow this you should make sure to remove the empty option This strange pattern ensures maximum compatibility with Angular 1x where an empty option is automatically inserted until a selection is performed To also allow unselection in Angular you must manually create the empty option and make sure that it is explicitly selected as default select multiple The select multiple only triggers a change when the Done button is pressed You can customize the button label by adding a button to the label element but note that this only configures the text on the button eg no event listeners are fired Select multiple One Two Three Four Five Cool apply changes Select multiple One Two Three Four Five Cool apply changes Select multiple One Two Three Four Five Cool apply changes input typeradio Radio element Generally used to choose something Choose wisely Red pill Blue pill Choose wisely Red pill Blue pill Choose wisely Red pill Blue pill input typecheckbox Checkbox element Generally used to indicate consent on forms Legally Binding Contract I agree to something I agree to something by default Legally Binding Contract I agree to something I agree to something by default Legally Binding Contract I agree to something I agree to something by default input typetextbox alternate version We call it the switch Used mainly for toggling preferencessettings Note that switch differs from the checkbox only by the order of HTML elements Settings Page Secret Feature Secret Feature On by default Settings Page Secret Feature Secret Feature On by default Settings Page Secret Feature Secret Feature On by default Errors and info To mark a control as invalid simply add the class tserror to the label Text Text Text To display an error message one must mark the control as errored using the tserror class as well as add the error message markup to the page Text Text An explanation of the error in question Another explanation of the error in question Text Text An explanation of the error in question Another explanation of the error in question To display an info section use the tsinfo class Text Text An information about the field Another information about the field Text Text An information about the field Another information about the field If you find a bug or need a feature Create GitHub Issue"},{"title":"Form Example","href":"components/forms/redesign.html","content":"Standard Text Text with custom icon Text with no icon Textarea Textarea Select One Two Three Select with placeholder One Two Three Select multiple One Two Three Four Five Cool apply changes Date Radios Option One Option Two Checkbox I agree I dont agree Switch I agree I dont agree Disabled Text Text with custom icon Text with no icon Textarea Textarea Select One Two Three Select with placeholder One Two Three Select multiple One Two Three Four Five Cool apply changes Date Radios Option One Option Two Checkbox I agree I dont agree Switch I agree I dont agree TODO Ghost optiongroup label only when all options are disabled Readonly Text Text with custom icon Text with no icon Textarea Textarea Select One Two Three Select with placeholder One Two Three Select multiple One Two Three Four Five Cool apply changes Date Note that readonly has no function on radio groups and checkboxes One can make a readonly field look normal with the tsnolock classname Text Multi Text Multi Date Multi Textarea Multi Textarea More Multi Textarea Select Multi One Two Three Select Multi One Two Three Multiselect multi One Two Three Four Five Cool apply changes Multiselect multi One Two Three Four Five Cool apply changes Errors Info Error Text An explanation of the error in question Another explanation of the error in question Info Text An information about the field Another information about the field Disabled info Text An information about the field Another information about the field Forms in Asides Check out the Form in that Aside Open the Aside Colored Forms Choose your color Dark Red Green Blue Purple Yellow LiteWhite Text Select One Two Three Date Text Textarea Textarea Select One Two Three Select multiple One Two Three Four Five Cool apply changes Date Radios Option One Option Two Checkbox I agree I dont agree Switch I agree I dont agree If you find a bug or need a feature Create GitHub Issue"},{"title":"","href":"components/forms/tabs.html","content":""},null,null,{"title":"Header Buttons","href":"components/header/index.html","content":"Header buttons Go go gadget Header"},null,{"title":"Icons","href":"components/icons/css.html","content":"Icons buttonhover ibefore fontfamily Open Sans important fontweight 600 tsdoxtabs edbmldeclareedbmlZCEiMv0asfunction edbml use strict var out edbmlout txt edbmlsafetext val edbmlsafeattr tsiconlogot1 tsiconlogot2 tsicondiscovery tsiconactivity tsicontodo tsiconnetwork tsiconcreatedocument tsiconalldocuments tsicondocument tsiconsales tsiconpurchases tsicondrafts tsiconapps tsiconusersettings tsiconsettings tsiconcompanyprofile tsiconlogout tsiconsupport tsiconchecked tsiconaccept tsicondone tsiconcheckedalt tsiconremove tsiconadd tsiconclose tsiconlocation tsiconaddfilter tsiconfollowed tsiconunfollowed tsiconsearch tsiconstatuschange tsiconedit tsiconrating tsiconshare tsiconindustry tsiconshowpicker tsiconwarning tsicontimer tsiconcomment tsiconmore tsiconusers tsiconownership tsiconcompanysize tsiconview tsiconreject tsicondispute tsiconmenuswitch tsicondelete tsiconcancel tsiconinfo tsiconforums tsiconaddfield tsiconfileaccess tsiconerror tsiconappactivate tsiconappactive tsiconfileattach tsiconreset tsiconsend tsiconsave tsiconproceed tsiconback tsicondownload tsiconbroadcastmessage tsiconinsertfrominventory tsicontriangleright tsicontriangleleft tsicontriangleup tsicontriangledown tsiconarrowright tsiconarrowleft tsiconarrowup tsiconarrowdown tsiconpreview tsiconlocked tsiconunlocked tsiconnext tsiconapprove tsiconcode tsiconhalt tsiconpay tsiconother tsiconmyapps tsiconcompanyevent tsiconsplit tsiconmerge tsiconassociated tsiconradio tsiconradioon tsiconcheckbox tsiconcheckboxon tsiconcheckboxindeterminate tsiconwrittenrequest tsiconcategories tsiconfavorites tsiconheart tsiconpreferred tsiconpin tsiconpreviouslyrequested tsiconcart tsiconarchive tsiconaddtoarchive tsiconcalendar tsiconselect tsiconcollaboration tsiconaddcurrentobject tsiconforward tsiconquestion tsiconphone tsiconbox tsiconusersassign tsiconusersadd tsiconusersremove sortforEachfunctionicon outhtml txticon return outwrite "},{"title":"Icons","href":"components/icons/iconspirit.html","content":"IconsSpirit This spirit is only used in Docs for now We should probably make this into a screenshot page This is a good old CSS icon We must always remember that the icon remains centered in the list item as the text wraps to multiple lin This icon is embedded via inline SVG As you can see the icon still remains centered vertically when the text wraps to multiple line This icon is loaded from external bundle 1 This icon is loaded from external bundle 1 This icon is loaded from external bundle 1 This icon is loaded from external bundle 2 This icon is loaded from external bundle 2 This icon is loaded from external bundle 2 If you find a bug or need a feature Create GitHub Issue"},{"title":"Icons","href":"components/icons/index.html","content":"Icons A library of icons that work great with Buttons Assign any of the icon classnames to an i element to get an icon Note that we like to reserve i for icons so if you need to emphasize text consider using em If you find a bug or need a feature Create GitHub Issue"},null,{"title":"Icons","href":"components/icons/list.html","content":"Icons tsdoxtabs Icons This is the definitive list of all supported icons There are 3 sizes displayed for each icon tsfontsizesmall 11px This size is used when an icon is attached to a form field tsfontsizeicon 22px This size is used most of the time when displaying icons 36px This size isnt used directly on the pages but its common to use icons on this size in the App Store icons of Apps tsuireadyfunction function geticontype color dark return item Icon type type color color function geticonrowtype description return geticontype geticontype geticontype type description var table tsuigeticons tablecols label 11px type iconssizetiny minwidth tsuiUNIT 3 tsfontsizeicon label 22px type iconssizestd minwidth tsuiUNIT 3 App Icon Size label 36px type iconssizeapp minwidth tsuiUNIT 3 label Classname type tstext flex 3 minwidth 200 label Description type tstext flex 10 minwidth 200 wrap true tablerows geticonrowtsicondiscovery Some horrible cool description goes here with MARKDOWN supportn Fulln Onn Awesome geticonrowtsiconactivity geticonrowtsicontodo geticonrowtsiconnetwork geticonrowtsiconcreatedocument geticonrowtsiconalldocuments geticonrowtsicondocument geticonrowtsiconsales geticonrowtsiconpurchases geticonrowtsicondrafts geticonrowtsiconapps geticonrowtsiconusersettings geticonrowtsiconsettings geticonrowtsiconcompanyprofile geticonrowtsiconlogout geticonrowtsiconsupport geticonrowtsiconchecked geticonrowtsiconaccept geticonrowtsicondone geticonrowtsiconcheckedalt geticonrowtsiconremove geticonrowtsiconquestion geticonrowtsiconmore geticonrowtsiconinfo geticonrowtsiconadd geticonrowtsiconclose geticonrowtsiconlocation geticonrowtsiconaddfilter geticonrowtsiconfollowed geticonrowtsiconunfollowed geticonrowtsiconsearch geticonrowtsiconstatuschange geticonrowtsiconedit geticonrowtsiconrating geticonrowtsiconshare geticonrowtsiconindustry geticonrowtsiconshowpicker geticonrowtsiconwarning geticonrowtsicontimer geticonrowtsiconcomment geticonrowtsiconusers geticonrowtsiconownership geticonrowtsiconcompanysize geticonrowtsiconview geticonrowtsiconreject geticonrowtsicondispute geticonrowtsiconmenuswitch geticonrowtsicondelete geticonrowtsiconcancel geticonrowtsiconforums geticonrowtsiconaddfield geticonrowtsiconfileaccess geticonrowtsiconerror geticonrowtsiconappactivate geticonrowtsiconappactive geticonrowtsiconfileattach geticonrowtsiconreset geticonrowtsiconsend geticonrowtsiconsave geticonrowtsiconproceed geticonrowtsiconback geticonrowtsicondownload geticonrowtsiconbroadcastmessage geticonrowtsiconinsertfrominventory geticonrowtsicontriangleright geticonrowtsicontriangleleft geticonrowtsicontriangleup geticonrowtsicontriangledown geticonrowtsiconarrowright geticonrowtsiconarrowleft geticonrowtsiconarrowup geticonrowtsiconarrowdown geticonrowtsiconpreview geticonrowtsiconlocked geticonrowtsiconunlocked geticonrowtsiconnext geticonrowtsiconapprove geticonrowtsiconcode geticonrowtsiconhalt geticonrowtsiconpay geticonrowtsiconother geticonrowtsiconmyapps geticonrowtsiconcompanyevent geticonrowtsiconsplit geticonrowtsiconmerge geticonrowtsiconassociated geticonrowtsiconradio geticonrowtsiconradioon geticonrowtsiconcheckbox geticonrowtsiconcheckboxindeterminate geticonrowtsiconcheckboxon geticonrowtsiconwrittenrequest geticonrowtsiconcategories geticonrowtsiconfavorites geticonrowtsiconheart geticonrowtsiconpreferred geticonrowtsiconpin geticonrowtsiconpreviouslyrequested geticonrowtsiconcart geticonrowtsiconarchive geticonrowtsiconaddtoarchive geticonrowtsiconcalendar geticonrowtsiconselect geticonrowtsiconcollaboration geticonrowtsiconaddcurrentobject geticonrowtsiconforward geticonrowtsiconphone geticonrowtsiconbox geticonrowtsiconusersassign geticonrowtsiconusersadd geticonrowtsiconusersremove "},null,null,{"title":"","href":"components/icons/tabs.html","content":""},{"title":"Inline Components","href":"components/index.html","content":"Inline Components tsdoxtabs Inline components These components depend on special markup structures and some may expose features though a JavaScript API Other than specifying the datats attribute as shown there is no need to initialize the components in any special way Button A true classic available in several flavors Primary Secondary Tertiary Primary Secondary Tertiary Primary Secondary Tertiary Primary Secondary Tertiary Primary Secondary Tertiary Primary Secondary Tertiary CompanyCard A unified way to show companies id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Tradeshift logo assetslogopng size 100249 location San Francisco California industry Software IT connection 2 id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Tradeshift logo assetslogopng size 100249 location San Francisco California industry Software IT connection 2 Form Another classic cant have webapps without them Text Text Text Textarea Textarea Textarea Date Date Date Select One Two Three Select One Two Three Select One Two Three Select multiple One Two Three Four Five Cool apply changes Select multiple One Two Three Four Five Cool apply changes Select multiple One Two Three Four Five Cool apply changes Choose wisely Red pill Blue pill Choose wisely Red pill Blue pill Choose wisely Red pill Blue pill Legally Binding Contract I agree to something I agree to something by default Legally Binding Contract I agree to something I agree to something by default Legally Binding Contract I agree to something I agree to something by default Settings Page Secret Feature Secret Feature On by default Settings Page Secret Feature Secret Feature On by default Settings Page Secret Feature Secret Feature On by default Icons We support a range of icons Here are a few randomly selected ones Menu Not to be confused with the main navigation this is simply a list of selectable items I have an icon on my right And a second line I have an icon on my left but skipped the second line I have an icon on my right And a second line I have an icon on my left but skipped the second line I have an icon on my right And a second line I have an icon on my left but skipped the second line Note A nice way to inform the user about something on the page This is not for status messages It also works on pagelevel You love the Note You love the Note You love the Note Search Unified search experience TabBar An easy way to show tabs Also works on pagelevel var tabbar tsuigettabbarexample tabbartabs label Tab One onselect function tsuiNotificationsuccessthislabel label Tab Two onselect function tsuiNotificationsuccessthislabel var tabbar tsuigettabbarexample tabbartabs label Tab One onselect function tsuiNotificationsuccessthislabel label Tab Two onselect function tsuiNotificationsuccessthislabel guiBroadcastaddguiBROADCASTDIDSPIRITUALIZE onbroadcast function var firstload true var tabbar tsuigettabbarexample tabbartabs label Tab One onselect function if firstload firstload false else tsuiNotificationsuccessthislabel label Tab Two onselect function tsuiNotificationsuccessthislabel Table Ranging from spreadsheetstyle editing to just showing some tabular data var table tsuigettableexample tablecols label Level type tsnumber label Character flex 2 label Alignment flex 2 tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil var table tsuigettableexample tablecols label Level type tsnumber label Character flex 2 label Alignment flex 2 tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil guiBroadcastaddguiBROADCASTDIDSPIRITUALIZE onbroadcast function var table tsuigettableexample tablecols label Level type tsnumber label Character flex 2 label Alignment flex 2 tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil Time Human readable time formatting UserImage Little avatars for the users "},{"title":"Menu","href":"components/menus/index.html","content":"Menu Not to be confused with the main navigation the tsmenu is simply a list of selectable items Assign datatsMenu to a menu element to initialize it as a Menu Use li elements to separate the menu items all of which follows the structure of a Button Item One Item Two Item Three Item One Item Two Item Three Item One Item Two Item Three Adding Icons The markup follows the convention for buttons Use a span and an i element to seperate text and icon simply reverse the two to make the icon go first I have an icon on my right I have an icon on my left I have an icon on my right I have an icon on my left I have an icon on my right I have an icon on my left Using the second linesub text To add a second line to the Menu item just add a sub with some text in it Im the first line Im the second line Im the first line Im the second line Im the first line Im the second line Select one To create a single select menu mark one and only one li with the tschecked classname and use the tsiconchecked classname for the icon i element Selected Not selected Selected Not selected Selected Not selected Select many To create a multi select menu simply add more classnames and icons Selected Also Selected Selected Also Selected Selected Also Selected The UI component makes no attempt to automatically manage these icons and classnames whenever a new menu item gets selected Disabled items You can mark any selection as readonly by adding the disabled attribute to the individual buttons Not selected Not selected Selected Not selected Not selected Selected Not selected Not selected Selected If you find a bug or need a feature Create GitHub Issue"},null,{"title":"","href":"components/modals/page1.html","content":"Pa"},{"title":"","href":"components/modals/page2.html","content":"Pa"},{"title":"Note","href":"components/notes/index.html","content":"Note You can use the Note to give information to the user about the whole page or a section of the page The Note should however not be used to display errors or warning messages please use the Notification for that To explain to the user what the page is about you can show a Note at the top Note that there should never be more than one pagelevel Note tsuiNote icon tsiconheart text This page explains how to use the Note component with some nice examples onclose function tsuiNotificationsuccessThe Note is gone tsuiNote icon tsiconheart text This page explains how to use the Note component with some nice examples onclose function tsuiNotificationsuccessThe Note is gone You can add buttons to the Note If you save a reference to the Note you can close it with any button var note tsuiNote buttons label Button type tsprimary onclick function noteclose var note tsuiNote buttons label Button type tsprimary onclick function noteclose You can also add some links via Markdown When a link is clicked the URL will be passed along to the onlink method As you can see below the URL can be just a key it doesnt have to be real URL tsuiNote text Choose link oneONE or twoTWO or threeTHREE onlink functionurl tsuiNotificationsuccessurl thisclose tsuiNote text Choose link oneONE or twoTWO or threeTHREE onlink functionurl tsuiNotificationsuccessurl thisclose If the link should indeed link to something make sure to provide the full protocol https Notes should not be used for internal navigation at least not yet You can use an inline Note to give information about a certain section of the page Only the pagelevel Note is closeable while inline Notes should stay on the page with the content You love the Note You love the Note Note without icon using simple HTML This is the iconless Note This is the iconless Note Inline Note with closeable function This is the closeable inline Note This is the closeable inline Note The Note will wrap to multiple lines if theres a lot of content inside Arcane spell failure charm domain cover dragon type enemy experience points versus Tradeshift family domain fighter and hardness hit die initiative check intelligence melee attack roll miniature figure movement modes Party planning domain point of origin powerful charge ray regeneration rogue special quality speed take 20 touch attack turned Fivefoot step ability class feature domain dying level luck domain negate ranged touch attack result speed surprise target total concealment unarmed strike Armor class base save bonus check conjuration divine spell falling objects fly law domain school of Tradeshift shield bonus threatened square war domain Ability damage acid effects burrow chaos domain class feature darkvision fullround action glamer subschool good subtype improved evasion incorporeal subtype ocean domain platinum piece size modifier You can use a Note in an Aside or a SideBar if you put the inline note as the first child of the tspanel Note in the Aside Note in the Aside If you find a bug or need a feature Create GitHub Issue"},{"title":"Notification","href":"components/notifications/index.html","content":"Notification Simple modals for providing users with notifications much like the JavaScript alert method Basic markdown may be used for links and formatting The success notification demands no user interaction tsuiNotificationsuccessYou did it tsuiNotificationsuccessYou did it The info warning and error notification must be accepted by the user tsuiNotificationinfoYou can do it tsuiNotificationwarningYou will fail tsuiNotificationerrorYou are wrong tsuiNotificationinfoYou can do it tsuiNotificationwarningYou will fail tsuiNotificationerrorYou are wrong An optional second argument specifies the button text tsuiNotificationwarningBeware Understood tsuiNotificationwarningBeware Understood You can configure a callback for when the Notification gets accepted tsuiNotificationinfoYou must accept it onaccept function tsuiNotificationsuccessWe knew you would tsuiNotificationinfoYou must accept it onaccept function tsuiNotificationsuccessWe knew you would Notifications support basic markdown for formatting and links Markdown for bold text and italic text and source code Markdown for a hyperlinkhttpwwwexamplecom When a link is clicked the URL will be passed along to the onlink method As you can see below the URL can be just a key it doesnt have to be real URL var text Choose link oneONE or twoTWO or threeTHREE tsuiNotificationinfotext onlink functionurl thisacceptthenfunction onfadeout tsuiNotificationsuccessurl var text Choose link oneONE or twoTWO or threeTHREE tsuiNotificationinfotext onlink functionurl thisacceptthenfunction onfadeout tsuiNotificationsuccessurl If the link should indeed link to something make sure to provide the full protocol https tsuiNotificationinfo Please visit Tradeshifthttpwwwtradeshiftcom tsuiNotificationinfo Please visit Tradeshifthttpwwwtradeshiftcom Note that all links will open in a new tab or window depending on the browser settings so you should not use links in Notifications for internal navigation at least not just yet If you find a bug or need a feature Create GitHub Issue"},{"title":"Pager","href":"components/pager/index.html","content":"Pager Provides a navigation menu with shortcuts for all kinds of paginated data Assign datatsPager to a menu or nav to initialize it as a Pager The component may be configured in HTML complete with an inline callback like in this example or you can configure it via a JavaScript API like in this example tsuigetmypager pager pagerpages 8 pagerpage 0 pageronselect functionpage consolelogpage tsuigetmypager pager pagerpages 8 pagerpage 0 pageronselect functionpage consolelogpage As you can see the Pager has no default outline and this will make it easier to embed into other components Heres a short summary of the Pagers properties and methods If you find a bug or need a feature Create GitHub Issue"},{"title":"Panels","href":"components/panels/index.html","content":" "},{"title":"Search","href":"components/search/index.html","content":"Search The Search is prominently featured in the Main ToolBar but you can use it anywhere on the page if you like Note that the API is in any case identical You can initialize a Search with datatsSearch The classname tsinset will add an outline so that we can see how it behaves on this white background The search field expands when the field is focused by the user or whenever theres a nonempty value in the field You can change the value like this var search tsuigetmysearch searchvalue Hello world var search tsuigetmysearch searchvalue Hello world To keep the field expanded at all times simply assign the CSS classname tsexpanded Search info The datatsinfo attribute works to show a title mouseover tooltip when the field is collapsed and a placeholder when the field is expanded Search callbacks The onsearch callback gets invoked when when the user presses ENTER var search tsuiToolBarsearch searchvalue Press ENTER here searchonsearch functionvalue tsuiNotificationsuccessvalue Search cleared var search tsuiToolBarsearch searchvalue Press ENTER here searchonsearch functionvalue tsuiNotificationsuccessvalue Search cleared If defined the onidle method gets called whenever the user pauses typing var search tsuiToolBarsearch searchvalue Try it now searchonidle functionvalue tsuiNotificationsuccessvalue var search tsuiToolBarsearch searchvalue Try it now searchonidle functionvalue tsuiNotificationsuccessvalue The onidle method may also be called when the field loses focus The idletime property controls the timeout value default is 500 milliseconds Here an overview of the properties and methods of the Search component If you find a bug or need a feature Create GitHub Issue"},{"title":"SideBars","href":"components/sidebars/index.html","content":"SideBars used to test that sidebars can be transferred from MAIN to BODY without breaking functionality since this always happens in V4 if false documentreadyfunction var elem mysidebar var main elemclosesttsmain alertmainget0 if mainlength 0 mainafterelem used to test delayed Angular initialization in Collaboration panel note that the title must also be removed to simulate collaboration if false documentreadyfunction setTimeoutfunction var elem mysidebar elemattrdatatsautoclose false 1000 tsdoxtabs SideBar The SideBar is a panel used for interactions directly related to the main content such as filtering and sorting a list of items Assign datatsSideBar to an aside to initialize as a SideBar The SideBar must be created with a child Panel SideBar content Also note tht the SideBar must be positioned before or after the Main element Toggle the SideBar In mobile breakpoint the SideBar is hidden and must be toggled forth manually If you resize to mobile view you can try it with this button Toggle SideBar You can toggle the SideBar like you would toggle an Aside var sidebar guigetmysidebar sidebaropen sidebarclose sidebartoggle Bonus panels You can put a Footer next to the Panel The Footer will stick to the bottom of the SideBar If you want this to be visible in mobile only as the current designs suggest you can assign it the classname tsshowmobileonly Nesting Asides You can make subsidebars by nesting Aside components in the tssidebar The Aside can be opened and closed like a normal Aside SideBar content Aside content Custom toolbar buttons The SideBar header works like a Toolbar You can add buttons with an API so well add a button to toggle that Aside we talked about var sidebar guigetmysidebar var header sidebarheader headerbuttonspush icon tsiconadd onclick function guigetmyasidetoggle var sidebar guigetmysidebar var header sidebarheader headerbuttonspush icon tsiconadd onclick function guigetmyasidetoggle This API is likely to change SideBar content Aside content Footer content The button below is only relevant in mobile view Toggle SideBar"},{"title":"","href":"components/sidebars/tabs.html","content":""},null,{"title":"Spinner","href":"components/spinners/index.html","content":"Spinner function spinelm elmattrdatatsbusy true setTimeoutfunction elmattrdatatsbusy false 1500 Spinner The Spinner can be used with Main Aside Table SideBar and Button You can assign the datatsbusy to the Main element to initialize a Spinner Main content Lets try that with jQuery var main mainfirst mainattrdatatsbusy Crunching data setTimeoutfunction mainattrdatatsbusy 1500 var main mainfirst mainattrdatatsbusy Crunching data setTimeoutfunction mainattrdatatsbusy 1500 If you want a blocking overlay you can use the datatsblocking attribute var main mainfirst mainattrdatatsblocking Crunching and blocking setTimeoutfunction mainattrdatatsblocking 1500 var main mainfirst mainattrdatatsblocking Crunching and blocking setTimeoutfunction mainattrdatatsblocking 1500 Aside and SideBar Assign the datatsbusy attribute to an Aside or SideBar to initialize a Spinner Aside content It will look like this var aside myaside asideattrdatatsopen true asideattrdatatsbusy Crunching data setTimeoutfunction asideattrdatatsbusy setTimeoutfunction asideattrdatatsopen false 250 1500 var aside myaside asideattrdatatsopen true asideattrdatatsbusy Crunching data setTimeoutfunction asideattrdatatsbusy setTimeoutfunction asideattrdatatsopen false 250 1500 Button Assign the datatsbusy attribute to a Button to initialize a Spinner Primary Show Spinner Table Assign the datatsbusy attribute to a Table to initialize a Spinner tsuigetmytable table tablecolsOne Two Tree tablerows A D G B E H C F I mytableattrdatatsbusy Loading setTimeoutfunction mytableattrdatatsbusy 1500 tsuigetmytable table tablecolsOne Two Tree tablerows A D G B E H C F I mytableattrdatatsbusy Loading setTimeoutfunction mytableattrdatatsbusy 1500 Aside content"},{"title":"Table Actions","href":"components/table/actions.html","content":"Selection actions The table actions are reserved for working with selections They work much like the buttons except the icon should never be omitted from an action since it is always displayed and not just in mobile breakpoint You can try to select something in this table var table tsuigettable1 tablecolsOne Two Threerows A B C D E F G H I selectableupdate function update var actions tableactions var maximum tablerowslength var counter tableselectedlength ifcounter 0 tablestatuscounter of maximum rows selected ifactionslength actionspush label Delete icon tsicondelete label Report icon tsiconhalt label Revert icon tsiconback onclick consolelogThe revert action was clicked else actionsclear tablestatusmaximum rows update var table tsuigettable1 tablecolsOne Two Threerows A B C D E F G H I selectableupdate function update var actions tableactions var maximum tablerowslength var counter tableselectedlength ifcounter 0 tablestatuscounter of maximum rows selected ifactionslength actionspush label Delete icon tsicondelete label Report icon tsiconhalt label Revert icon tsiconback onclick consolelogThe revert action was clicked else actionsclear tablestatusmaximum rows update The actions method both sets and gets the actions If you omit the argument youll get the current actions jQuery style You can use array methods like push pop shift unshift splice and so on to manage actions just note that the actions length is a readonly property Heres a summary of the actions collection and action model If you find a bug or need a feature Create GitHub Issue"},null,null,null,null,null,null,null,null,null,null,null,null,null,{"title":"Table Build","href":"components/table/building.html","content":"Table Build tsdoxtabs Building the Table You can build your cols and rows with a compact syntax tsuigetmytable table tablecolsOne Two Tree tablerows A D G B E H C F I tsuigetmytable table tablecolsOne Two Tree tablerows A D G B E H C F I You can also declare columns as objects The objects have a label property tsuigetexample1 table tablecols label One label Two label Three tsuigetexample1 table tablecols label One label Two label Three This will come in handy when we need to assign extra properties to the columns If we set the type property to tsnumber the text will be rightaligned except in the first column tsuigetexample2 table tablecols label Type label Value type tsnumber tablerows Random number Mathrandom tsuigetexample2 table tablecols label Type label Value type tsnumber tablerows Random number Mathrandom We can also declare rows as objects with a list of cells This syntax will allow us to mark the row as selected you can read more about selection tsuigetexample3 table tableselectablerows cells A D G selected true cells B E H cells C F I tsuigetexample3 table tableselectablerows cells A D G selected true cells B E H cells C F I The individual cells can also be declared as objects if the displayed text should be different from the hidden value which can be anything you like tsuigetexample4 table tablerows cells value 1 text One value 2 text Two value 3 text Three tsuigetexample4 table tablerows cells value 1 text One value 2 text Two value 3 text Three You can update a single row whenever you like Here with compact syntax tsuigetexample5 table tablerows A B C D E F tablerow1 Mathrandom Mathrandom Mathrandom tsuigetexample5 table tablerows A B C D E F tablerow1 Mathrandom Mathrandom Mathrandom You can of course also update a single cell Here with compact syntax tsuigetexample6 table tablerows A B C D E F tablecell1 1 Mathrandom tsuigetexample6 table tablerows A B C D E F tablecell1 1 Mathrandom You can use array methods like push pop shift unshift splice reverse and so on to mange the rows Just note that the length property is readonly tsuigetexample7 table var rows tablerows rowspush1 2 3 rowsunshift4 5 6 rowssplice0 0 7 8 9 rowsreverse tsuigetexample7 table var rows tablerows rowspush1 2 3 rowsunshift4 5 6 rowssplice0 0 7 8 9 rowsreverse Here a summary of the methods that deal with building the Table"},{"title":"Table Buttons","href":"components/table/buttons.html","content":"Table buttons The Table supports buttons and we will soon add some futher documentation For now we will simply recommend that you dont use buttons unless the Table is maximized This feature however also doesnt have any documentation var table tsuigettable1 tablecolsOne Two Threerows A B C D E F G H I buttons label One type tsprimary label Two type tssecondary label Three onclick consolelogThe tertiary button was clicked var table tsuigettable1 tablecolsOne Two Threerows A B C D E F G H I buttons label One type tsprimary label Two type tssecondary label Three onclick consolelogThe tertiary button was clicked The buttons method both sets and gets the buttons If you omit the argument youll get the current actions jQuery style You can use array methods like push pop shift unshift splice and so on to manage buttons just note that the buttons length is a readonly property TODO The Table breakpoint should be local to the Table not the window If you find a bug or need a feature Create GitHub Issue"},{"title":"Table Click","href":"components/table/clicking.html","content":"Table Click tsdoxtabs Clicking the cells You can make the Table body clickable The rowindex and cellindex refer to the indexes in the JSON arrays and not the table as shown on the screen They are in other words not affected by sorting and paging and searching var popup tsuiNotification tsuigetexample8 table tablerows A D G B E H C F I tableclickablefunctionrowindex cellindex popupsuccessRow rowindex Cell cellindex var popup tsuiNotification tsuigetexample8 table tablerows A D G B E H C F I tableclickablefunctionrowindex cellindex popupsuccessRow rowindex Cell cellindex "},{"title":"Table Collaboration","href":"components/table/collaborate.html","content":"Table Collaboration tsdoxtabs Table Collaboration This API is likely to change at some point You can activate a dedicated collaboration button in the statusbar var popup tsuiNotification tsuigettable1 table tablecollabbuttonfunction onclick popupsuccessGo collaborate colsA B C Drows 1 4 7 10 2 5 8 11 3 6 9 12 var popup tsuiNotification tsuigettable1 table tablecollabbuttonfunction onclick popupsuccessGo collaborate colsA B C Drows 1 4 7 10 2 5 8 11 3 6 9 12 The button triggers a callback but there is no default behavior associated The API to initialize and resume a Collaboration thread will be defined elsewhere When you are done with the button you can hide it again tsuigettable1collabbuttonnull tsuigettable1collabbuttonnull"},{"title":"Table Config","href":"components/table/configuring.html","content":"Table Config tsdoxtabs Configuring the Table You can make the table configurable by a button in the statusbar var popup tsuiNotification tsuigettable1 table tableconfigbuttonfunction onclick popupsuccessGo configure colsA B C Drows 1 4 7 10 2 5 8 11 3 6 9 12 var popup tsuiNotification tsuigettable1 table tableconfigbuttonfunction onclick popupsuccessGo configure colsA B C Drows 1 4 7 10 2 5 8 11 3 6 9 12 The button triggers a callback but there is otherwise no default UI associated Since the visibility of columns is always a candidate for configuration the ColModel supports a visible property that can be used to hide columns tsuigettable1 table var cols tablecols function hideindex colsindexvisible false ifindex setTimeoutfunction next hideindex 1000 3 tsuigettable1 table var cols tablecols function hideindex colsindexvisible false ifindex setTimeoutfunction next hideindex 1000 3 Heres a summary of these things"},{"title":"Table Demo","href":"components/table/demo.html","content":"Table Demo tsmain overflowy hidden tsdoxtabs"},null,{"title":"Table Edit","href":"components/table/editing.html","content":"Table Edit tsdoxtabs Editing the cells We can make the Table editable with a callback that fires on change tsuigettable1 table tablerows Single asterisks is used for italic text Double asterisks is used for strong text Single backtick is used for monotype text Double tilde can be used to Strike text editablefunction oneditrowindex cellindex value consolelogSend to backend value tablecellrowindex cellindex value tsuigettable1 table tablerows Single asterisks is used for italic text Double asterisks is used for strong text Single backtick is used for monotype text Double tilde can be used to Strike text editablefunction oneditrowindex cellindex value consolelogSend to backend value tablecellrowindex cellindex value All cells are assumed editable unless negated in the column definition tsuigettable6 table tablecols label Edit label Edit label Dont edit editable false rows V V X editablefunction oneditri ci value thiscellri ci value tsuigettable6 table tablecols label Edit label Edit label Dont edit editable false rows V V X editablefunction oneditri ci value thiscellri ci value If you switch to verbose syntax you can also disable editing per row tsuigettable7 table tablerows cells X X X editable false cells V V V cells V V V editablefunction oneditri ci value thiscellri ci value tsuigettable7 table tablerows cells X X X editable false cells V V V cells V V V editablefunction oneditri ci value thiscellri ci value You can override both columns and rows by specifying editabletrue on the individual cells Again this would best be done using verbose syntax Multiline editing You can enter newlines by holding SHIFT on ENTER You will need to enter two newlines to create a paragraph Note however that we only show the first paragraph unless the column is set to wrap var popup tsuiNotification tsuigettable8 table tablecols label Wrapped column wrap true label Unwrapped column rows Hold SHIFT while pressing ENTER to add a second paragraph New paragraph ignored editablefunction oneditri ci value tablecellri ci value var popup tsuiNotification tsuigettable8 table tablecols label Wrapped column wrap true label Unwrapped column rows Hold SHIFT while pressing ENTER to add a second paragraph New paragraph ignored editablefunction oneditri ci value tablecellri ci value Input validation Note that the actual update is a manual proces This will give you a break to validate the input In this example well show the errors in a Notification var popup tsuiNotification tsuigettable2 table tablerows 1 1 2 3 5 8 13 21 34 55 editablefunction oneditri ci value value Numbervalue ifisNaNvalue tableinvalidri ci popuperrorPlease type a number onaccept function tablefocusri ci else consolelogSend to backend value tablecellri ci value var popup tsuiNotification tsuigettable2 table tablerows 1 1 2 3 5 8 13 21 34 55 editablefunction oneditri ci value value Numbervalue ifisNaNvalue tableinvalidri ci popuperrorPlease type a number onaccept function tablefocusri ci else consolelogSend to backend value tablecellri ci value We can report the errors in a less annoying way if we pass a string as we mark the cells invalid The message will show in the statubar when the cell is focused Well also initialize the statusbar with an empty string so that it doesnt awkwardly pop into existance function formatvalue return new DatevaluetoDateString function validvalue return isNaNnew DatevaluegetTime tsuigettable3 table tablestatusrows value 19851026 text format19851026 value 20151021 text format20151026 value 19551112 text format19551112 editablefunction oneditri ci value ifvalidvalue consolelogSend to backend value tablecellri ci value value text formatvalue else var message Please use the format YYYYMMDD tableinvalidri ci message function formatvalue return new DatevaluetoDateString function validvalue return isNaNnew DatevaluegetTime tsuigettable3 table tablestatusrows value 19851026 text format19851026 value 20151021 text format20151026 value 19551112 text format19551112 editablefunction oneditri ci value ifvalidvalue consolelogSend to backend value tablecellri ci value value text formatvalue else var message Please use the format YYYYMMDD tableinvalidri ci message When the cell is eventually updated it automatically becomes valid Lets talk more about the difference between text and value in the example above Text versus value It doesnt always matter but its important to note that we edit the value while we show the text Heres another example to illustrate the difference tsuigettable4 table tablerows value 1000 text 100000 value 2000 text 200000 value 3000 text 300000 editable tsuigettable4 table tablerows value 1000 text 100000 value 2000 text 200000 value 3000 text 300000 editable This way we can edit validate and persist the data in a uniform format in this case JavaScript numbers while displaying a regionalized or otherwise customized format We can exploit this creatively by editing a document ID and showing the document title for example Remember to update verbosely tablecellrowindex cellindex text 400000 value 4000 because otherwise the text becomes identical to the value Also note that the editable callback will always serve the value as a string so it may be nescessary to convert it to a number Heres the more complete example function formatn return ntoFixed2replaceBd3dg tsuigettable5 table tablerows value 1000 text format1000 value 2000 text format2000 value 3000 text format1000 editablefunctionri ci value value Numbervalue ifisNaNvalue tableinvalidri ci else tablecellri ci value value text formatvalue function formatn return ntoFixed2replaceBd3dg tsuigettable5 table tablerows value 1000 text format1000 value 2000 text format2000 value 3000 text format1000 editablefunctionri ci value value Numbervalue ifisNaNvalue tableinvalidri ci else tablecellri ci value value text formatvalue Heres an overview of the editing related features API for knowing when something is invalid everything is valid How to visually differentiate editable versus noneditable cells"},{"title":"Table Extras","href":"components/table/extras.html","content":"Table Extras function getbuttonlabel name value return item Button type tssecondary tsmicro label label name name value value function getswitchname value checked return item Switch name name value value checked checked function geticontype color return item Icon type type color color black function getimagesrc width height return item Image src src width width 100 height height 100 background true function getuserimagename src return item UserImage name name src src tsdoxtabs Table extras Table cells can be declared via JSON using verbose syntax But we can use a different JSON syntax to declare cells with special content The Table will generate components based on the value of the item property and this can be one of the following Button Icon Image Switch UserImage Button This function will return the JSON to generate a Button in the Table function getbuttonlabel name value return item Button type tssecondary tsmicro label label name name value value To conserve browser memory in very large Tables the onclick callback is not supported But you can intercept the Button click via the name and value property you just need to assign the onbutton method to the Table tsuigettable1 table tablerows Apple getbuttonBuy this Apple buy 123 Orange getbuttonBuy that Orange buy 456 Banana getbuttonBuy the Banana buy 789 tableonbutton functionname value rowindex cellindex ifname buy tsuiNotificationsuccessProduct value ordered tablecellrowindex cellindex getbuttonCancel order tsuigettable1 table tablerows Apple getbuttonBuy this Apple buy 123 Orange getbuttonBuy that Orange buy 456 Banana getbuttonBuy the Banana buy 789 tableonbutton functionname value rowindex cellindex ifname buy tsuiNotificationsuccessProduct value ordered tablecellrowindex cellindex getbuttonCancel order The Button value can be anything from strings and numbers and booleans to objects and arrays if that helps Just dont assign any functions because those will be ignored The value also doubles as a sorting criteria of the column is sortable so bear that in mind Here are the configurable properties of the ButtonModel Icon This function returns the JSON to generate an icon function geticontype color black return item Icon type type color color The type configures the icon classname and the optional color property can be one of black medium red green blue and purple tsuigettable3 table tablerows geticontsiconsales geticontsiconcancel medium geticontsiconerror red geticontsiconaccept green geticontsiconinfo blue geticontsiconfavorites purple tsuigettable3 table tablerows geticontsiconsales geticontsiconcancel medium geticontsiconerror red geticontsiconaccept green geticontsiconinfo blue geticontsiconfavorites purple Here are the configurable properties of the IconModel This interface may change as we upgrade to SVG icons Image This function returns the JSON to generate an Image function getimagesrc width height return item Image src src width width 100 height height 100 Note that the width and height properties are mandatory for us to fix the dimensions of the image even before it is loaded This will prevent the page from jumping around tsuigettable4 table tablerows getimageassetsimage1jpg getimageassetsimage2jpg getimageassetsimage3jpg getimageassetsimage4jpg tsuigettable4 table tablerows getimageassetsimage1jpg getimageassetsimage2jpg getimageassetsimage3jpg getimageassetsimage4jpg We can also declare a boolean property background in the JSON If set to true the image will be rendered as a backgroundimage to unlock further processing via CSS for example via the backgroundsize property Here are the configurable properties Switch This function returns the JSON to generate a Switch function getswitchname value checked return item Switch name name value value checked checked The Switch is the checkbox that looks like some kind of switch tsuigettable2 table tablerows Spam mails getswitchtoggle 123 true Prank calls getswitchtoggle 456 true House visits getswitchtoggle 789 false tableonswitch functionname value checked rowindex cellindex ifname toggle var status checked enabled disabled tsuiNotificationsuccessService value status tsuigettable2 table tablerows Spam mails getswitchtoggle 123 true Prank calls getswitchtoggle 456 true House visits getswitchtoggle 789 false tableonswitch functionname value checked rowindex cellindex ifname toggle var status checked enabled disabled tsuiNotificationsuccessService value status TODO We could need a layout feature to fix the width of the switch column Here are the configurable properties of the SwitchModel UserImage This function returns the JSON to generate a UserImage function getuserimagename src return item UserImage name name src src If you like you can also specify a size to adjust the width and height of the image tsuigettable5 table tablerows getuserimageJim Bob Johnson assetsjimpng getuserimageKarl Benson getuserimageMarshall Garrett getuserimageKelvin Castro tsuigettable5 table tablerows getuserimageJim Bob Johnson assetsjimpng getuserimageKarl Benson getuserimageMarshall Garrett getuserimageKelvin Castro Here are the properties of the UserImage"},{"title":"Table Filter","href":"components/table/filtering.html","content":"Table Filter tsdoxtabs Filtering the columns The table doesnt really know anything about filtering but it does support a button which can be assigned an icon and an onclick method Perhaps you can use this to create your own filtering UI in an Aside or something var table tsuigettable1 var popup tsuiNotification tablecols label Hello type tsnumber button icon tsiconaddfilter onclick function thisicon tsicondelete popupsuccessClicked var table tsuigettable1 var popup tsuiNotification tablecols label Hello type tsnumber button icon tsiconaddfilter onclick function thisicon tsicondelete popupsuccessClicked You can change the icon and the onclick method as often as you like var table tsuigettable1 var popup tsuiNotification var mycol tablecols0 mycolbuttonicon tsiconview mycolbuttononclick function popupsuccessClicked again var table tsuigettable1 var popup tsuiNotification var mycol tablecols0 mycolbuttonicon tsiconview mycolbuttononclick function popupsuccessClicked again When you implement filtering you can either build the rows from scratch or update the visible property of the existing row like in this example var table tsuigettable2 var popup tsuiNotification var isodd false tablerows1 2 3 4 5 6 7cols label All numbers type tsnumber button icon tsiconaddfilter info Show odd rows onclick function isodd isodd thisicon isodd tsicondelete tsiconaddfilter thisinfo isodd Show all rows Show odd rows tablecols0label isodd Odd numbers All numbers tablerowsforEachfunctionrow i rowvisible isodd i 2 0 true var table tsuigettable2 var popup tsuiNotification var isodd false tablerows1 2 3 4 5 6 7cols label All numbers type tsnumber button icon tsiconaddfilter info Show odd rows onclick function isodd isodd thisicon isodd tsicondelete tsiconaddfilter thisinfo isodd Show all rows Show odd rows tablecols0label isodd Odd numbers All numbers tablerowsforEachfunctionrow i rowvisible isodd i 2 0 true The button gets hidden by the search because it doesnt look right to have both Let us know if that becomes a problem"},{"title":"Table Formatting","href":"components/table/formatting.html","content":"Table Formatting tsdoxtabs Formatting the cells The Table supports a simple subset of Markdown out of the box tsuigettable1 table tablerows Italic text Strong text Strike text monotype text tsuigettable1 table tablerows Italic text Strong text Strike text monotype text Use double newline n to render multiple paragraphs We also have UL lists tsuigettable2 table tablerows Para 1nnPara 2nnPara 3 Item 1n Item 2n Item 3 tsuigettable2 table tablerows Para 1nnPara 2nnPara 3 Item 1n Item 2n Item 3 To support links youll first need to call the linkable method just to remind yourself that you may now become exposed to phishing attacks tsuigettable3 table tablelinkable tablerows Please visit Tradeshifthttpwwwtradeshiftcom tsuigettable3 table tablelinkable tablerows Please visit Tradeshifthttpwwwtradeshiftcom When you link to something make sure to include the protocol https and note that links should not be used for internal navigation at least not just yet If the link should work more like a button you can intecept the click action with the onlink callback In this case you can use any string as the href var popup tsuiNotification tsuigettable4 table tablelinkablefunction onlinkanystring popupsuccessanystring rows Choose link oneONE or twoTWO or threeTHREE var popup tsuiNotification tsuigettable4 table tablelinkablefunction onlinkanystring popupsuccessanystring rows Choose link oneONE or twoTWO or threeTHREE "},null,null,null,{"title":"Table","href":"components/table/index.html","content":"Table Contrary to common belief the datatsTable attribute should not be assigned to a table element because the component will create that table itself Instead we can assign it to a div All features are controlled through an API as outlined on the following pages If you find a bug or need a feature Create GitHub Issue"},{"title":"Table Layout","href":"components/table/layouting.html","content":"Layout the columns Columns sizes can flex relative to other columns These last two columns are twice the width of the first column which is assumed a flex value of 1 tsuigetexample4 table tablecols label Level type tsnumber label Character flex 2 label Alignment flex 2 tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil tsuigetexample4 table tablecols label Level type tsnumber label Character flex 2 label Alignment flex 2 tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil If the Table is small like in the example above you can still run into truncated text If this becomes a problem you can either wrap the column cells tsuigetexample5 table tablecols label Level type tsnumber label Character flex 2 wrap true label Alignment flex 2 tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil tsuigetexample5 table tablecols label Level type tsnumber label Character flex 2 wrap true label Alignment flex 2 tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil or you can assign it a minwidth in pixels If the table is big enough the flex values still count so we will leave them in noting that the first column is still assumed flex1 tsuigetexample6 table tablecols label Level type tsnumber minwidth 55 label Character flex 2 minwidth 300 label Alignment flex 2 tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil tsuigetexample6 table tablecols label Level type tsnumber minwidth 55 label Character flex 2 minwidth 300 label Alignment flex 2 tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil To ensure that the Table can work on a small screen or even a mobile phone you should strongly consider specifying a minwidth on all the columns On small screens this may result in a horizontal scrollbar but we dont consider this a problem for the Table A suggested feature creep would be to let the user control column visibility via the config button so that he can compare two columns without scrolling back and forth Finally theres an option to assign a fixed width to one or more columns This will override any flex It doesnt work if you assign it to all the columns so please dont do that tsuigetexample7 table tablecols label Level type tsnumber width 55 label Character minwidth 300 label Alignment tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil tsuigetexample7 table tablecols label Level type tsnumber width 55 label Character minwidth 300 label Alignment tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil If you find a bug or need a feature Create GitHub Issue"},{"title":"Table Paging","href":"components/table/paging.html","content":"Table Paging tsdoxtabs Paging the rows You can limit the number of visible rows with the max method If the table contains more rows a Pager will be created An equivalent method size also fixes the height of the Table so that the pager footer never jump up and down getJSONassetsrowdatajson functionjson tsuigetexample9 table tablecols label ID type tsnumber label Name flex 2 label Price type tsnumber tablerowsjsonmax5 getJSONassetsrowdatajson functionjson tsuigetexample9 table tablecols label ID type tsnumber label Name flex 2 label Price type tsnumber tablerowsjsonmax5 You can track the page with the onpage method if for some reason you need that tableonpage functionindex consolelogindex called whenever the user changes page If you would like to manage paging yourself because you have a billion products and dont want to fetch them all at once you can create your own pager var popup tsuiNotification tsuigetbigdatatable table tablemax10cols label ID type tsnumber label Name flex 2 label Price type tsnumber tablepager pages 5 page 0 onselect loadpage function loadpageindex var url assetspage index json getJSONurl functionjson var n jsonlength popupsuccessLoaded n rows tablerowsjson loadpage0 var popup tsuiNotification tsuigetbigdatatable table tablemax10cols label ID type tsnumber label Name flex 2 label Price type tsnumber tablepager pages 5 page 0 onselect loadpage function loadpageindex var url assetspage index json getJSONurl functionjson var n jsonlength popupsuccessLoaded n rows tablerowsjson loadpage0 If you need to update the index later on for example to support history navigation it is recommended that you change the page property of the existing Pager instead of initializing a whole new Pager You can just call the same method without arguments mytablepagerpage 23"},{"title":"Table Search","href":"components/table/searching.html","content":"Searching the columns You can setup a SearchModel for any column via the search property We ship the Table with a builtin search mechanism but youll still need to call it The Table search method takes a column index and the string to search for getJSONassetsrowdatajson functionjson tsuigetexample10 table tablerowsjsonmax4cols label ID type tsnumber search tip Search product ID onidle functionvalue tablesearch0 value label Product Name flex 1 search tip Search product names onidle functionvalue tablesearch1 value getJSONassetsrowdatajson functionjson tsuigetexample10 table tablerowsjsonmax4cols label ID type tsnumber search tip Search product ID onidle functionvalue tablesearch0 value label Product Name flex 1 search tip Search product names onidle functionvalue tablesearch1 value The search algorithm is extremely primitive and to some degree it always will be at least until the Table can be loaded separately from other components because file size You can focus the search field if you like either by setting the focused property to true in the JSON or by calling the focus method sometime later on var table tsuigetexample10 tablecols1searchfocus var table tsuigetexample10 tablecols1searchfocus Here an overview of the properties and methods of the Search model If you find a bug or need a feature Create GitHub Issue"},{"title":"Table Select","href":"components/table/selecting.html","content":"Table Select tsdoxtabs Selecting the rows You can mark rows as selectable with the method of that name The callback fires whenever one or more rows changes state The arguments selected and unselected arguments are both arraysofrowindexes var table tsuigettable1 var popup tsuiNotification tablerows cells A D G selected true cells B E H cells C F I tableselectablefunction debugselected unselected popupsuccess JSONstringifyselected JSONstringifyunselected join var table tsuigettable1 var popup tsuiNotification tablerows cells A D G selected true cells B E H cells C F I tableselectablefunction debugselected unselected popupsuccess JSONstringifyselected JSONstringifyunselected join You can mark individual rows as unselectable with the selectable property var table tsuigettable5 var popup tsuiNotification tablerows cells A D G cells B E H selectable false cells C F I tableselectablefunction debugselected unselected popupsuccess JSONstringifyselected JSONstringifyunselected join var table tsuigettable5 var popup tsuiNotification tablerows cells A D G cells B E H selectable false cells C F I tableselectablefunction debugselected unselected popupsuccess JSONstringifyselected JSONstringifyunselected join You can control selection using the methods select unselect and toggle The methods take one or more indexes or an array of indexes as arguments var table tsuigettable3 tableselectablerows A E I B F J C G K D H L select0 1toggle2 3 var table tsuigettable3 tableselectablerows A E I B F J C G K D H L select0 1toggle2 3 You can also omit the argument to select unselect or toggle everything tsuigettable3toggle tsuigettable3toggle You can retrieve the selected indexes as an array with the selected method var table tsuigettable3 var array tableselected var popup tsuiNotification popupsuccessJSONstringifyarray var table tsuigettable3 var array tableselected var popup tsuiNotification popupsuccessJSONstringifyarray You can also confirm selection by passing one or more indexes or an array var table tsuigettable3 var popup tsuiNotification iftableselected0 1 2 3 popupsuccessAll selected else popupwarningYou must select them all var table tsuigettable3 var popup tsuiNotification iftableselected0 1 2 3 popupsuccessAll selected else popupwarningYou must select them all If you add columns to the table youll get a selection menu in the header var table tsuigettable2 tableselectable tablecolsOne Two Three tablerows cells A D G cells B E H cells C F I var table tsuigettable2 tableselectable tablecolsOne Two Three tablerows cells A D G cells B E H cells C F I The menu selects or deselects all visible rows If there are multiple pages in the table youll be presented with the opportunity to select all pages getJSONassetsrowdatajson functionjson var table tsuigettable4selectable tablecolsID Name Pricerowsjsonmax5 getJSONassetsrowdatajson functionjson var table tsuigettable4selectable tablecolsID Name Pricerowsjsonmax5 If you are loading the table data incrementally so you manage paging yourself you might like to know when all or none is selected via the menu The Table supports two additional callbacks that can be assigned via selectable tableselectableonselect onselectall onunselectall tableselectableonselect onselectall onunselectall You can also assign these methods directly tableonselect functionselected unselected tableonselectall function consolelogAll tableonunselectall function consolelogNone tableonselect functionselected unselected tableonselectall function consolelogAll tableonunselectall function consolelogNone Heres a summary of the methods that deal with row selection"},{"title":"Table Sort","href":"components/table/sorting.html","content":"Table Sort tsdoxtabs Sorting the columns You can make the Table sortable with a callback that triggers whenever a column is clicked We ship the Table with a builtin sort mechanism but youll still need to call it The sort method takes a column index and a direction tsuigetexample6 table tablecols Animal label Price type tsnumber rows Donkey 700 Baboon 1500 Coyote 250 Albatross 50 sortablefunctionindex ascending tablesortindex ascending tablesort0 true tsuigetexample6 table tablecols Animal label Price type tsnumber rows Donkey 700 Baboon 1500 Coyote 250 Albatross 50 sortablefunctionindex ascending tablesortindex ascending tablesort0 true The index is the column index and the ascending argument alternates whenever the same col is clicked twice If you manage your own sorting routine you can control the appearance of the column using selected and ascending tsuigetexample12 table tablecols label Example selected true ascending false setIntervalfunction var col tablecols0 ifcolselected colselected colascending colascending 1000 tsuigetexample12 table tablecols label Example selected true ascending false setIntervalfunction var col tablecols0 ifcolselected colselected colascending colascending 1000 Importantly note that the cell values must all be declared as numbers in order to sort numerically You can declare a hidden value while showing a human readable text using verbose syntax tablerows value 1 text One value 2 text Two value 3 text Three Custom sort Standard sorting only deals with numbers and strings If you need some kind of more advanced sorting for example if the value contains arrays or objects you can implement custom sort per column via the sort method tsuigetexample7 table tablecols label Fruit sort functionval1 val2 ascending sort random return Mathrandom 05 1 1 rowsBanana Apple Grape Pear sortablefunctionindex ascending tablesortindex ascending tsuigetexample7 table tablecols label Fruit sort functionval1 val2 ascending sort random return Mathrandom 05 1 1 rowsBanana Apple Grape Pear sortablefunctionindex ascending tablesortindex ascending "},{"title":"Table Sort","href":"components/table/status.html","content":"Table Sort tsdoxtabs Status messages We can show a message in the statusbar The message could be something like Showing 1020 out of 123 products or 23 products selected tsuigettable1 table tablestatusThis is the message tablerows 1 4 7 2 5 8 3 6 9 tsuigettable1 table tablestatusThis is the message tablerows 1 4 7 2 5 8 3 6 9 TODO Note about markdown in the status message"},{"title":"Table Styling","href":"components/table/styling.html","content":"Table Styling mytable tholdprice backgroundcolor rgb250 200 200 mytable tdoldprice backgroundcolor rgb255 225 225 mytable thnewprice backgroundcolor rgb200 250 200 mytable tdnewprice backgroundcolor rgb225 255 225 example2 tdpalered backgroundcolor rgb255 225 225 example2 tdpalegreen backgroundcolor rgb225 255 225 example2 tdpaleblue backgroundcolor rgb225 225 255 example3 tdveryspecial backgroundcolor rgb225 225 255 tsdoxtabs Styling the table The column type property works as a classname for both headers and cells tsuigetmytable table tablecols label Product label Regular Price type tsnumber oldprice label Sale price type tsnumber newprice tablerows Apple 130 100 Orange 075 050 Banana 200 125 tsuigetmytable table tablecols label Product label Regular Price type tsnumber oldprice label Sale price type tsnumber newprice tablerows Apple 130 100 Orange 075 050 Banana 200 125 This means that you can style the columns using CSS that looks like this mytable th oldprice background red newprice background green td oldprice background pink newprice background lime A similar property works for the rows if you switch to verbose syntax You will of course need to defined these classnames somewhere in your CSS file tsuigetexample2 table tablerows cells A D G type palered cells B E H type palegreen cells C F I type paleblue tsuigetexample2 table tablerows cells A D G type palered cells B E H type palegreen cells C F I type paleblue Finally the individual table cells can be styled with the type property Again you will have to switch to verbose syntax in order to declare this property tsuigetexample3 table tablerows cells text Normal text Normal text Special type veryspecial tsuigetexample3 table tablerows cells text Normal text Normal text Special type veryspecial "},{"title":"","href":"components/table/tabs.html","content":""},{"title":"","href":"components/tabs.html","content":""},{"title":"Time","href":"components/times/index.html","content":"Time Use the Time component to show a human readable time your app Assign datatsTime to a time to initialize it as a Time If you do not trust the users device time you can set the realtime attribute to mark the current time the moment when the page renders If you set an invalid datetime it will simply show the string If you find a bug or need a feature Create GitHub Issue"},{"title":"Local Time","href":"components/times/langs.html","content":"Time TODO This should go into a screenshot for the test suite edbmldeclareedbml14yR7I0asfunction edbml use strict var out edbmlout txt edbmlsafetext val edbmlsafeattr outhtml da deCH de enGB enUS en es fi fr hu id it ja ms nbNO nl no pl ptBR ptPT ro ru se svSE zhCN zhTWsplit forEachfunctioncode outhtml txtcode outhtml return outwrite If you find a bug or need a feature Create GitHub Issue"},{"title":"","href":"components/times/tabs.html","content":""},null,null,{"title":"UserImage","href":"components/userimages/index.html","content":"UserImage If the user didnt upload a photo the UserImage will generate a fallback image based on his or her name You can initialize a UserImage by assigning datatsUserImage to an img element A fallback image will be generated based on the users name if the image has no src attribute or if the image somehow failed to load You also can define initials in parentheses For exampleKarl Alfonso Benson KB you will get KB as an initials The image defaults to a size of 44x44 pixels If you prefer a different size youll need to specify both width and height as attributes in the HTML You can select users from a menu by adding the classname tsusermenu to a standard Menu while also replacing the icon i element with a UserImage Jim Bob Johnson jimbobcompanycom Karl Benson karlcompanycom Marshall Garrett marshallcompanycom Jim Bob Johnson jimbobcompanycom Karl Benson karlcompanycom Marshall Garrett marshallcompanycom Jim Bob Johnson jimbobcompanycom Karl Benson karlcompanycom Marshall Garrett marshallcompanycom If you find a bug or need a feature Create GitHub Issue"},null,null,null,null,null,null,null,null,null,{"title":"Buttons","href":"design/copy/buttons.html","content":"Buttons Button copy should be consistent and descriptive just like this subheader Buttons are crucial when it comes to copy for two reasons First they are one of the main ways in which users interact with the product Whenever a button is pressed something will happen Second buttons are among the most spacelimited elements in the UI which means that button copy needs to be extremely sharp With this in mind buttons on Tradeshift need to have two specific qualities they need to be collectively consistent and individually descriptive What does this mean Collectively consistent It is essential that the user can recognize buttons as such This is in large part made true through visual design theres a very limited and well defined set of possibilities for how buttons should look However this can also be strengthened by button copy being consistent in terms of how it relates to its context We achieve this through the following rules The button that begins the flow must work together with the one that ends it to make the flow a selfcontained unit All actions on Tradeshift that result in flows that require more than one step have two buttons that act as gates one to initialize the flow and one to finalize it The copy on these two buttons should be written with this in mind As a general rule if the opening button contains an action Reject document then the same verb should be present in the finalizing button On the other hand buttons that do not include an action for example Settings can have a more generic finalizer such as Done If a button results in the opening of a new page or a picker the title of said page or picker must be consistent with the name of the button So a button that reads Reject connection request should not lead to a picker that reads select value In very specific cases the title of the destination can read differently from the button but in 999 of cases they should read exactly the same Individually descriptive Whilst we want buttons to be consistent in how they relate to their context we also want them to be tailored to this context This means that as a general rule we do not want generic nondescript buttons that read proceed continue done or back Rather the copy on a button should be as descriptive as possible in terms of what the button will achieve of course within the length restraints implied Following the rule of thumb from the principle above if the button is related to an action then always use the verb in the button Furthermore if the verb is an action that can have multiple logical objects then include the object as well for example Reject can refer to documents connections and potentially more so describe what is being rejected If you find a bug or need a feature Create GitHub Issue"},{"title":"Copy in the Development Process","href":"design/copy/dev.html","content":"Copy in the Development Process When it comes to producing good copy embedding it into the development process is just as important as following the principles guidelines and rules If writing copy is not taken seriously as a task and allocated adequate time resources and interest the end result will not be good The following guidelines should help each product team to incorporate copywriting into the development process Copywriting is a skill and should ideally be done by the most capable Writing copy is a skill in and of itself and whilst it is related to a number of other skills it is definitely a skill that requires practice effort and knowledge Knowledge of the English language is a necessary but not sufficient skill and even skilled people will produce poor copy when rushed What this means is that each team should allocate copywriting to whoever is the most capable In some teams this might be the designer in others it might be the PM and in others it might be a developer What is important is that this is a conscious decision and not left to be picked up by a stressed PM on the day before release Good copy takes time effort and iterations Again no matter how amazing someone is at writing copy a truly good result can only be achieved through iteration and effort The first drafts for copy should be produced as early as possible in the development process and these should be discussed and iterated on much like everything else If you find a bug or need a feature Create GitHub Issue"},{"title":"Emails","href":"design/copy/emails.html","content":"Emails Emails are a crucial and highly complex aspect of the product Get it right When it comes to emails the complexity level is very high for 2 reasons There are many fields that must be filled with text sender subject headers body buttons explanations Emails are consumed in a context outside Tradeshifts control There are many different types of emails and things like tone etc will vary depending on the goal of the email Well now go through the different elements that comprise an email However before doing that two important questions must be asked Is this email necessary What is the goal of this email These questions may seem superfluous but it is important to be sure that only emails that are necessary and useful to the user are sent As such never take for granted that an email should exist At Tradeshift one requirement for an email being deemed necessary is that the email has a call to action for the user emails that do not encourage the user to take some action are not worth sending As such when answering the second question it is a good idea to keep the call to action in mind this will help in creating a good and cohesive email Once the purpose and call to action are determined we can proceed to the email itself As far as copy is concerned there are five sections that need to be created in an email sender subject title body and buttons Well go through these one at a time Sender This is a simple field where consistency rules There are two options for the sender When the email is a system email that is unrelated to any other user the sender should in most cases be Tradeshift When the email is related to an interaction between users the sender should be the user taking the action that results in an email via Tradeshift Subject Again the way the subject is written will very much depend on the nature of the email Nevertheless the subject is crucial since it plays the biggest role in determining whether the email will be read at all Having amazing copy inside the email is irrelevant if the email is never opened The most important thing to keep in mind is that emails revolve around the Call to Action CTA If an email does not have a relevant and important CTA then it is not worth sending There are two options for how the subject line should relate to the CTA when the action needed is critical for the continuation of a process and when it is not Note that this dichotomy is not necessarily the same as the action being important in a business sense an action can be very important businesswise but not be crucial per this definition For example a document being rejected in a small business context is a very important notification in a business sense but it is not critical in terms of being a bottleneck On the other hand a request for changes to a supplier registration form IS critical since the user will not be able to send invoices until the requested changes are made When the action is deemed critical the action should be frontloaded in the email by being the focus of the subject line So in the above example of a customer requesting changes on a suppliers registration form the subject line would read Your Supplier Registration form for customer requires some changes Other examples of subject lines for critical actions could be Action needed Register to Nike Supplier Network A document needs coding On the other hand when the action is not critical then the subject line should inform the user of the event that has occurred The call to action can then be introduced inside the email Subject lines for these types of email include the following user has sent you an invoice user accepted your connection request Your public profile is missing your logo Title The title section is quite a bit simpler as it is very much tied to the subject line The title should be very descriptive and summarize the purpose of the email for the user What this means is that the title can to a great extent mirror the subject line Following the examples above email titles could read as follows Subject Action needed Register to Nike Supplier Network Title As a supplier to Nike Inc you must complete the supplier registration on Tradeshift to be able to do business with Nike Subject user has sent you an invoice Title user has sent you an invoice on Tradeshift Body The copy in the body is where the majority of the information is conveyed This copy is also what leads the user to the button with the CTA so this section should provide the user with all of the information they might need to click on the button If the subject and title did not include the call to action you have received an invoice then it can be included here you have received an invoice from X Click the button below to see and accept or reject it If the call to action was included in the subject then this can be repeated along with an explanation of why the CTA is needed Buttons Currently Tradeshift emails typically contain a single button with the main CTA This button should be descriptive and tell the user exactly where in the product they will land In terms of functionality the button should take the user directly to the task needed they should not have to find their way once they click the button Thus an email informing the user of a new item on their To Do list should have a button leading the user to the item itself and not to the list as a whole As for the rest buttons on emails should follow the same guidelines as buttons in the rest of the product Read more in the buttons guidelines If you find a bug or need a feature Create GitHub Issue"},{"title":"Error Messages","href":"design/copy/errors.html","content":"Error Messages Error messages should be short and amazingly precise embodiments of the copy principles Error messages are extremely important yet they are the ones that are most often done carelessly or as an afterthought Error messages are what stands between a user continuing to be a user when something goes wrong and that user giving the program another chance Error messages are the copy that appears at the worst possible time Whatever it was that the user wanted to achieve was not achieved At best the outcome is irrelevant and at worst work time or worse may have been wasted As such error messages should do everything possible to convince the user to give the software another shot So what should an error message do 1 Be informative and concise Both of these are equally important Both extremes are problematic Too concise results in poor information transfer The most important thing is that the user knows what went wrong and what they should do next An error message that is too concise thus wont give enough information For example Something is broken This error message is certainly concise but it does not provide the user with any information besides the fact that their desired and expected outcome did not occur Conversely it can also be that an error message has too much information or information that is not easily decipherable An error message with too much information might read like The backup did not complete successfully An error ocurred The following information might help you resolve the error If an MM error is returned which is not defined in the standard FsRtl filter it is converted to one of the following errors which is guaranteed to be in the filter In this case information is lost however the filter correctly handles the exception 0xC00000EA Backup time 11292006 1157 AM Microsoft The important part is thus to provide enough information to give the user a clear indication of how to proceed but not so much that the user becomes more confused or simply gives up An error message with the right balance of concise and informative could be An error occurred while attempting to send your document Please try again If the issue persists please contact support 2 Keep in mind who is reading the error message Related with the point above You dont want to give the old lady information that would be interesting for the developer you want to give her the information she needs to solve her problem 3 Indicate the potential next steps Provide the user with the required steps they should take to either remedy the error or to arrive at the intended outcome It is important to always include the next step even when it is not something the user can solve themselves The following series of examples from Tradeshift show how we took a bad error message and iterated it into a good one At its earliest stage the error message looked like this CloudScan encountered an error while processing Document to Recipient This error message is not fantastic It makes it clear to the user which document caused the error and how the outcome differed from the intended but it does not provide the user with any information regarding what she should do next Thus we might change it to CloudScan encountered an error while processing Document to Recipient The most likely reason for this error is that the PDF file is corrupted Make sure that the PDF file can be opened in your PDF viewer This is better even though it is longer It provides the user with a clear action to take in order to solve the problem However it could still be improved As it is right now the most likely explanation is given But what happens if that is not the explanation The user might open the PDF in their reader just fine If this happens then they are in the same place as before without knowing what to do next Of course it can be that after this we do not have a next best explanation However its important to provide the user with a next action In this case we can add one more bit to our error message CloudScan encountered an error while processing Document to Recipient The most likely reason for this error is that the PDF file is corrupted Make sure that the PDF file can be opened in your PDF viewer If the issue persists please contact support It is important to give an action to the user even if we have no idea what is the correct way for the user to solve the issue In that case if the only solution is for the user to write support say that The user might do it by themselves but its better that were offering a solution than the user thinking they have to chase support around for a product that should be working in the first place By doing this we alleviate the pain that the user is experiencing due to the error For example this error message was shown when document delivery failed for an unknown reason Unable to send document Now it may very well be that we do not know why But a user faced with this problem is completely lost Nothing is gained by the brevity in this case Now if we add a few more words we can make the user feel a lot better even if we dont really have any more information than unknown error Due to an unknown error we were unable to send the document Please try sending it again If the issue persists please contact support We still dont know the cause of the error but two things happen here that didnt before First we are honest about not knowing this instead of looking lazy Second we encourage the user to ask us for help This shows that we care and provides a better user experience at the time where the user is at the lowest satisfaction point If you find a bug or need a feature Create GitHub Issue"},{"title":"UI Copy Principles","href":"design/copy/index.html","content":"Product copy principles Copy is an aspect of UI design that is often left by the wayside With a product that handles both sensitive and complicated processes it is essential that the design is supported by strong copy In the same way that the design decisions rest upon a set of principles copy decisions follow a similar pattern The following principles are meant to give very highlevel explanations for some of the decisions that we have made with regards to how copy should be and what it should do All of the other sections within these copy guidelines are informed by these principles Copy should above all else be informative and drive the experience forward Tradeshift is a complicated product for a complicated industry There is already a lot about the industry we work in that is very confusing so the copy should be as clear as possible This principle might seem obvious but it really is at the core of copy strategy This principle informs all the other ones in this list and every single line of copy on Tradeshift should aim to satisfy this principle Copy should be as concise as possible but clarity should not be sacrificed in favor of brevity Brevity is a good thing but not to the exclusion of everything else Following principle number one above brevity is only good insofar as it leads to informative copy Thus brevity is one extreme of an axis but not the goal An extremely short piece of copy can also be extremely uninformative an error occurred In such cases increased length is the preferred option in order to achieve maximum information transfer an unidentified error occurred during the uploading process Please try again If this problem persists please contact Tradeshift support In terms of tone copy should be friendly and casual but serious Were new young and exciting but were still dealing with peoples businesses money and other serious things This is a fine line to tread Tradeshift should not be boring and soulless but it still needs to be taken seriously A casual friendly tone is good You havent added a picture to your profile yet What are you waiting for Pop culture references These are not the droids youre looking for or even worse internetculture references are not Product copy should still feel natural when spoken out loud If a piece of copy doesnt feel natural in a context of one person explaining something to another then its not good enough Consistency is critical for a positive customer experience Product copy should be consistent across different parts of the product Marketing messages appearing within the product and emails generated by product activity should also be consistent with product copy to ensure understanding This consistency applies mostly to product names terminology key words and error messages but also applies to tone style punctuation format etc The page Terminology Cheat Sheet is the main resource to ensure consistency Product copy should assume as little previously existing knowledge as possible from the user In keeping with design principles Tradeshift users are very rarely expert users and in many cases the tasks they do at Tradeshift are not the principal tasks of their position As such product copy should not assume that the user possesses any deep technical industry or other specific knowledge If it sounds like an engineer talking to another engineer its not good enough If it sounds like an accountant talking to another its not good enough If it sounds like a lawyer talking to another lawyer or a lawyer talking to anyone its not good enough Copywriting is part of good design This means that copy is not something that gets added once a design has been finalized Rather copy is integral to the design process This means that placeholder copy is not good enough This does not mean that copy needs to be perfect from the very first wireframe What it does mean however is that copy cannot be Lorem Ipsum until an hour before deployment It is very much acceptable to write preliminary copy and to iterate on it as the whole design is iterated but copy is as important as layout in terms of providing a good user experience If you find a bug or need a feature Create GitHub Issue"},{"title":"Menu Pickers","href":"design/copy/pickers.html","content":"Menu Pickers With regards to copy there are three main sections in a picker The title the body and the buttons The layered lists we call Pickers are an essential aspect of how UIs are structured on Tradeshift Given that some of the most important choices on the platform are made through these copy on them is very important This is exacerbated by the fact that due to the layered structure a flow can become quite complex with layers being added and removed many times before the flow is over Thus it is essential for the copy in pickers to do two things 1 keep the user from getting lost and 2 push the action forward The title When it comes to the first objective of picker copy the title pulls most of the weight The title itself then has to do two things First it has to be able to tell the user exactly what needs to be done in this picker This means that somebody who looks at a picker without having just opened it should be able to know by reading the title what they were doing and what is expected of them Secondly the titles should give a sense of flow and continuity to the process Overall the user reading the title of a picker should know where they are and what is expected of them The first one is a matter of sharp and accurate description For example a picker whose body is a calendar could have as a title Choose A Date This would be a bad title since a user reading this without remembering how they got there would not know what the date is for A much better header for a picker with a calendar could be Set Due Date With this title the user knows that the date is the due date for an invoice and not the date of emission or any other date In a vacuum it might seem like a very small difference but all of these little things aggregate to make the product enjoyable and easy to use With regards to flow and continuity the best way to ensure this is to put together each title with the copy of whatever it was that triggered this picker Thus using the due date example above Clicking on Due in the create invoice page opens a picker named Due in and choosing specific date results in set a due date So when writing the title for a picker always look at it side by side with what triggered it The body The body is less straightforward because it can include very many different elements Broadly though they can be divided in two categories explanation copy and interactable elements The first type does not appear in all pickers only in cases where theres need for clarification regarding the purpose of the picker The guidelines for these are quite simple In these cases remember that clarity is king You will not be adding this type of copy unless its an already fairly complex flow so the only goal of this copy should be clarity Forget personality forget casual tone and focus on being clear The second broad category of copy in the body of pickers are the different types of value selectors themselves These can take the form of checkboxes radio buttons calendars free text boxes and more For these the same overall rules apply Clarity especially in labels but also the options themselves is the main priority The buttons Finally the last element that appears on pickers are buttons These buttons are no different than the buttons everywhere else in the product so the same guidelines should be followed Read more at the buttons guidelines If you find a bug or need a feature Create GitHub Issue"},{"title":"","href":"design/copy/tabs.html","content":""},{"title":"Terminology & Cheat Sheet","href":"design/copy/terms.html","content":"Terminology and Cheat Sheet The purpose of this section is to provide a condensed list of rules and terms for writing UI copy These are not specific or limited to certain parts of the product or elements in the UI but rather act as a set of broadly applicable rules In addition to this list of standard terms the rules that follow should help in writing good copy These rules are meant to be used by those planning on writing significant amounts of copy If youre interested in very specific aspects for example error messages you should look for those specific guides These rules will not miraculously help you write amazing copy if writing is just not for you though so if this is the case get someone else to help Remember that writing copy is very much a skill and knowing english is not enough Treat copywriting with respect and you will have a greater chance of coming up with something great Leave it until the last minute or as an afterthought and the end result will reflect this Do use Do not use Reason Connection Contact We focus on action and relationships Connection is action oriented while contact is static Recipient Receiver A receiver refers to a machine while a recipient is the correct term when talking about people invoice Invoice Do not capitalize words in the middle of a sentence wants to connect with you wants to join your network joining a network is ambiguous The action is to connect and networks are then formed organically Connection request Network request We focus on the action which is the connection network is ambiguous Document status Document state Status is generally understood in business state is tech jargon StatusVoid StatusVoided Voided is only the past tense of the verb to void and never an adjective Supplier Vendor Both are fine we have chosen supplier as a matter of consistency Validate Transcribe Transcribing connotes a time consuming and arduous task At Tradeshift we use clever technology to do these things so there is no need to transcribe only review and validate Validator Reviewer see above Processing in queue Processing indicates motion and progress whilst in queue signifies lack thereof Always attempt to include subject verb and articles in a sentence This is so that copy does not sound like a robot Sentences like Error importing file are technically correct but do not convey meaning well Being technically correct is not enough copy needs to read as a person explaining something to another Never sacrifice clarity in order to sound casual Copy should be whenever possible casual natural and friendly but clarity remains the top priority Be specific and precise with your word choice Search isnt the same as filter send might not be the same as submit and cancel is not the same as go back Particularly in actionoriented copy make absolutely sure that what you say is what you mean to say Avoid overusing jargon and be very wary of abbreviations Following design principles Tradeshift is a product with a very wide user base and is not expected to be a primary working tool As such copy should aim to inform users with a very wide variety in knowledge Of course sometimes it is impossible to avoid jargon but consider it carefully Abbreviations on the other hand are almost never OK Site should be Website Info should be Information and Invite should be Invitation Dont fall for the people dont read trap This has been repeated as a mantra for a very long time but UX experts across the board agree that this is not true Specially when it comes to headers and buttons users read Do not allow copy to be steered by this assumption Avoid using passive voice Passive voice invoice was sent by you creates awkward sentences where the subject is deemphasized Unless the intention is specifically to do this do NOT use passive voice Do not leave copywriting to the last minute Writing copy is a task like any other and requires time thought and effort to come up with a good result If you leave it until the last minute it is going to be bad If you write the first thing that comes to mind and call it a day it is going to be bad So instead of filling a design with Lorem Ipsum start working on the copy as an integral part of the design and iterate on it like you would anything else If you find a bug or need a feature Create GitHub Issue"},{"title":"Design Principles","href":"design/index.html","content":"Design principles By taking the following eight principles into account when building a Tradeshift application youll maximize your chances of creating a good user experience For most people Tradeshift is not their primary work tool It means that these people will only use Tradeshift occasionally Hence we generally dont consider the user an expert user and the core parts of Tradeshift have been designed with this in mind This doesnt mean we cannot or shouldnt provide powerful interfaces that cater to experienced users though By adapting the interface through a users repeated use and providing powerful shortcuts expert users will be able to experience a productivity boost 1 Remember users choices Users often need to repeat their work tasks Make sure to remember the users previous choices and inputs to support future choices If at all possible automate the mundane tasks Adjust defaults with used values Provide access to previously used values Whenever applicable ask the user if the used values should be new defaults When a user starts using Tradeshift the list of currency options contains one suggested currency the one used in the company registration country If the user uses another currency this newly used currency will appear as an option the next time the user needs to fill out the currency value This way lists of regularly used values are created Opposite principle Always providing the same ground zero to users no matter when or how many times the user has used your application Simultaneously clearing previously used values This may be relevant in other types of applications where values are never reused or where different users share one account 2 Build learning into the UI Consistent use of the design patterns provided in this guide is important to support the users learning and recognition Reuse and consistent use will give the user the ability to apply knowledge from one functional area to another lowering the cognitive load and increasing performance So do only invent new design patterns when absolutely necessary Reuse design patterns to provide an experience of recognition Be mindful of the users first run experience Learning to work with dynamic option lists in the context of selecting a unit type here aided by a first run embedded description creates knowledge about how to solve other tasks The currency selector uses the same design pattern as the unit type selector The user can now leverage previous experience since the designs are based on the same pattern Opposite principle Individual applications on mobile phones especially games are often wildly different to establish individual identity and to better optimize to very narrow tasks supported by that specific app But since allmost Tradeshift apps are extensions all related to the core consistency is chosen 3 Keep users in task solution mode People come to Tradeshift to work with their business data and flows not to work with buttons inputs or manuals Keeping the users in the functional flows is important Avoid forcing the user to outofcontext settings pages to change things that could be adjusted incontext Provide sensible defaults that potentially prevent the user from wanting to change a setting in the first place Further avoid forcing the user to read FAQs and manuals out of context Be mindful of the users first run experience Whenever a user intends to export Tradeshift data make sure you know why If you can provide a view of the data or functionality thatd keep the user in the flow the user gets a better experience and your product is better Avoid settings pages Keep help descriptions in the app not outside Understand why and when the users want to export application data Consider if an improvement could solve the need Example Letting the user update address and company registration information from the public profile page makes settings pages for these details unnecessary Opposite principleEncouraging the user to spend significant time understanding your app properly before using it Eg by letting the user read a manual and a separate getting started guide Then still before use configuring the product for correct use Many medicalhealthcare products work this way as improper understanding can be dangerous Quickbooks is an example of a settings heavy application as well but it seems Intuit is moving away from this approach as it clearly Tradeshifts internal tests show makes initial use harder 4 Mobile first Global reach includes users who are not primarily working in front of a computer all day Its users whore working on the road and even users who dont ever have access to a laptopdesktop computer Most often its valuable thinking the mobile use cases first itll improve the experience for all other users Given the diversity of the markets Tradeshift is made available in and the shift towards mobile in more mature markets dont underestimate the mobile scenarios Consider the mobile use cases first Be optimistic when considering the mobile use cases Be aware that many Tradeshift users will have both a regular computer and a mobile device Some will not have a computer ExampleMany users check their email continuously on their smartphone A primary vehicle for notifying users and getting users to complete tasks in Tradeshift rely on email as communication channel such as when a new invoice is received Allowing smooth transition from an email notification telling about the received invoice to actually accepting or rejecting the invoice on the same device allows the user to react faster Also the user doesnt need to mark the email as unread or otherwise flag it to see it on a desktop computer later Opposite principleExpert systems where users are expected to work on a computer in a known locationsetting and where the user is not pulled into the application via eg email notifications While we do have this kind of applications on the platform the majority of future features integrate tightly into email and the ability to respond from these 5 Help the user focus Establish a visual hierarchy on you application pages that support the prioritized features the page is intended to present Most used features get dominant colors positions and sizes while less used features are visually downprioritized The design patterns are created to guide you to doing this Make sure to only present the data the user needs to make decisions at any given time Avoid just rendering out all the data you have just because you have it Render out only the data necessary for your use cases Establish a clear visual hierarchy optimized for the use cases you intend to solve The prioritization you do when designing your app is cognitive load you lift off the end users shoulders Opposite principle Specialistexpert systems used daily by users can typically present more data information and actions than nonexpert occasionally used systems The expert user has plenty time to master complex interfaces and will eventually receive intensive product training So in those cases intricate shortcuts and an abundance of information in large tables can be empowering Many Tradeshift users though are often occasional users whose primary profession is normally not within the functional areas covered by Tradeshift eginvoice creator enterprise invoice coder 6 Provide a sense of context Whenever the user navigates your application make sure to provide enough visual clues that the user understands where and why he arrived at a certain screen Buttons with explanatory text is one solution Animations to explain the scene changes is another solution Stacking pickers is an example of this The visual stacking provides a trail back while each layer appears in a way that supports the same concept Think beforeafter states into any action Use clues such as animation to show how one item relates to another Opposite principle Expert systems again or alternatively text based systems such as DOS prompt or Terminal Here the visual clues have been almost completely omitted and rely on the user to contain and know context 7 If it looks easy its easier to get started Tradeshift encourages use by having an interface that looks easy to use Instruments such as slightly oversized elements and typography plenty of whitespace clear colors simple iconography must all be considered when laying out your application Avoid things like overcrowding areas unnecessary divider lines stacking content closely microtypography and unaligned elements Use a visualUI designer if in doubt Spend time ensuring your application screens are well laid out and correspond with Tradeshifts UI guidelines Reevaluate all elements presented in your application UI and consider if they need to be there to let the user make decisions and actions Use a UI designer to get the visuals right if in doubt Opposite principle Heavier applications such as 3D software or even games can allow a steeper learning curve as users both need all functionality at their fingertips all the time much less linear flow of actions and time and interest in feature discovery isnt unexpected 8 Do enduser testing No heuristics in the world can replace enduser testing Get to know the truth about the target users ability to interact with your app Improve when necessary Opposite principle When building internal tools where the users are within arms reach The benefits of having direct access to every user can eliminate the need for classical enduser testing as the product in use is the actual testing If you find a bug or need a feature Create GitHub Issue"},null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,{"title":"Buttons","href":"design/patterns/buttons.html","content":"Buttons A collection of button styles exist to visually prioritize the possible actions in your application Styles include the color size and position of the buttons Applying these button styles correctly will help the user focus on the most likely next action By prioritizing the user flows in your application you will know which flows are most likely to be used by the majority of users One way of making these most likely paths clear to the users is by applying the appropriate button styles Four main button styles exist Primary button The most likely action the user will take On desktop and tablet size interface this button is almost always positioned in the top right corner of the window or its attached at the end of the content in the main content area Secondary buttons Functionality that many users will need but without which the application pages would still work The secondary buttons are located to the left of the primary button on desktop and tablet size interface Tertiary buttons Functionality that isnt often used by the majority of users should be styled and positioned as tertiary buttons Example exporting or deleting a viewed document Kill button Functionality that performs a deletion or rejection action These buttons are visually styled to alert the user and are most often placed in pickers to confirm an action Example confirming the deletion of a document Its worth spending some time reviewing functionality such as invoice creation and viewing in Tradeshift to see these principles in action Above is the invoice creation screen The Send button is primary for this functionality Preview is secondary and Discard is tertiary A number of other tertiary actions are grouped within the tripledot icon These are actions such as importing document contents from a file sending a test email with the document attached etc Above is a Kill button which confirms the action of deleting a document Its styled to indicate the destructive nature of its action If you find a bug or need a feature Create GitHub Issue"},{"title":"Emails","href":"design/patterns/emails.html","content":"Emails Points to keep in mind Have exactly one message in your email Be concise and to the point of why did the user receive this email what reaction is expected from the user and which other party triggered the email to be sent Present the most expected action as a primary action button just below the introductory text Dont advertise All promotion is managed by Tradeshift and sent out through optin newsletters Application emails are for actionsappevents only Irrelevant content dilute the signalstrength from other Tradeshift emails Make your emails work on mobile devices If you find a bug or need a feature Create GitHub Issue"},{"title":"Full page apps","href":"design/patterns/fullpage.html","content":"Full page apps Apps may run with the Tradeshift navigation interface the chrome visually hidden while still technically running inside the Tradeshift chrome and showing the Tradeshift URL in the address bar The Supplier Registration app takes over the full viewport while running on Tradeshift Under normal conditions any app should rarely have the need to take over the full viewport The approach is also only recommended for flows where new users need to perform certain actions before using Tradeshift Expect users who are used to using Tradeshift to want to have access to the global navigation If you find a bug or need a feature Create GitHub Issue"},{"title":"Structure","href":"design/patterns/index.html","content":"UI Structure Due to the responsive nature of Tradeshift you should pay careful attention to how UI elements transform across screen sizes The applications navigation elements transform as illustrated in the following Small phone size devices 1270px The Global Menu is expanded and the TopBar behaves as in tablet style Global Menu The Global Menu is the primary way for the user to switch between the main functional areas Core applications such as Document Creation and User Settings provide a Global Menu Item for the user to access these applications directly The Global Menu is present in all contexts and cannot be disabled It will however expand and collapse based on available screen space TopBar The TopBar serves multiple purposes and takes on different appearances In the examples above the TopBar contains buttons for actions but other uses of the TopBar such as tabbed navigation are possible Main Main is where most task solving takes place Tradeshift applications are designed on a fluid grid which lets applications fluidly fill out the entire main content area on all screen resolutions up to 1270 point width Attempts should always be made to fill out the main content area and if this is not possible you should visually define the boundaries of the functionality If you find a bug or need a feature Create GitHub Issue"},{"title":"Navigation Items","href":"design/patterns/nav.html","content":"Navigation Items Menu items can be inserted in the Global Menu to provide direct access to your app An application icon must be provided as well as a name for your application A highlight color can be specified for your menu item allowing integration of your visual identity in combination with your custom icon Shortcuts are only available in tablet size and are stacked vertically along the left side of the screen under the Tradeshift logo mark The shortcuts are basically global menu items that have been defined to also appear in the shortcut list This means that the shortcuts are a subset of the global menu items Only specify your global menu item as a shortcut if frequent and repeated access to your functionality on mobile devices is necessary TopBar The Topbar can be customized in a few different ways Buttons for the TopBar When using the TopBar to present buttons the actions assoicated to the buttons are expected to manipulate the entirety of page contents they are top level actions The buttons are also contextual and can change with application state The invoice creation example has document delete save and send as contextual actions These actions modify the entirety of whats on the page More finegrained controls such as adding lines belong to the contents of the document and should never appear in the contextual bar as actions An alternative example connector app and connections page is when the page contains a collection of objects In this case the contextual action of adding another object to the collection is allowed as contextual action as it alters the collection being the highest level on that kind of page Tabbed navigation The TopBar can also contain tabs with the purpose of splitting related contents into subsections that can be processed individually in any given order An example is this documentation Progresstabbed navigation When a tabbed navigation is preferred but theres a requirement for users to process all tabs in order the progresstabbed TopBar is used Note that the progresstabbed navigation leaves ample space for a flow headline by keeping the progress tabs below the TopBar space Progresstabbed navigation works well for setup flows where all steps are required such as a custom registration flow Filtering and searching For managing complex lists the TopBar can be completely exchanged with search and filter functionality This is especially usable for long lists such as the documents list pages If you find a bug or need a feature Create GitHub Issue"},{"title":"Option Lists and Pickers","href":"design/patterns/pickers.html","content":"Option lists and pickers In most cases Tradeshifts user interface doesnt rely on the standard select element for option selection Instead options are presented in layered lists This is what we call Pickers Structurally the Pickers allow the presentation of more complex selection scenarios than the select element allows In the concept illustration below selecting an invoice due date requires either a relative or an absolute value This can be combined in one seamless flow using Pickers Pickers have been designed to work similarly across different devices and screen sizes as a picker panel basically is a collection of form elements styled to meet phone styling requirements For huge lists with hundreds or thousands of options a search element can be enabled In the following example the list of options contains a few hundred unit types Only the previously used ones are shown Access to the full list is provided by free text search Searching for units in a picker Copy Guidelines Writing copy for pickers for the most part consists of writing copy for a bunch of individual elements that can be found elsewhere in the product There are essentially three distinct groups of copy when it comes to pickers Title The title should be as descriptive as possible regarding what the goal of the user is Furthermore the title should match the copy of the element that triggered the opening of the picker Body The body can include two different elements clarificationexplanation copy and value selectors The selectors should follow the same guidelines as throughout the rest of the product The clarificationexplanation copy should be as clear as possible No personality no humor this is strictly a help text in a complex flow and its only goal is to clarify the actions expected of the user Buttons Some pickers will include buttons When they do these follow the rules of buttons in the rest of the product Read more about buttons including copy here or read the indepth section on button copy Ways of presenting options Pickers are used whenever you need a field value populated from existing data Ie if the user clicks an input element and a value is returned to a field on the existing page a picker should most often be used Here are the standard option Single value selection Multiple value selection Advanced value selection Drilldown with nested values in a hierarchy of pickers tree structure Option manipulation Add option Modify option Remove option part of edit Navigation options Object navigation hub click invoice in documents list and get options in picker Advancedcustom use Invoice line transformation across devices Simple options Checkboxes multi select or single value boolean or radio buttons single select can be used when the following is true Less than 5 options in list Options cannot be manipulated The standard select elementdropdown is never used In cases that is needed always use a picker as this provides a more consistent user experience for value selection If you find a bug or need a feature Create GitHub Issue"},{"title":"Switches","href":"design/patterns/switches.html","content":"Switches Switches also referred to as toggles in regular UI design lingo are used for enablingdisabling options In most cases a switch should be used instead of a standalone checkbox Dont use switches when When a single confirmationcheck is required to progress to next step eg signing or confirming Here a checkbox should be used as both enabled and disabled state in a switch should be allowed values in any context If you find a bug or need a feature Create GitHub Issue"},{"title":"Tables","href":"design/patterns/tables.html","content":"Tables The core table designs in Tradeshift aim to be similar to best practices and existing standards Due to the responsive nature of Tradeshift UI some extra considerations should be made to ensure that the user can access and understand the information contained For tables the following concepts should be considered Linewrapping When enabled text inside table cells will break to multiple lines if theres not enough horisontal space Disabling linewrapping makes every row same height as text inside cells is only one line Proper handling of relative cellwidths and overflow is important when lines are not allowed to wrap Rowselection When enabled each line has a checkbox in the first left column This column is fixed so if the table scrolls horisontally the selector first column stays in place This allows the user to make selections while browsing all columns Clickable rows In many cases table rows represent single objects and are clickable This is symbolised by having a last column containing three dots Responsive column handling To better adapt to the available screen space mainly width careful consideration of textoverflow and hidingshowing columns should be done In cases where an entire row is clickable and links to an object columns can often be left out in smalldevice table views as the contents of these columns will be visible on the object anyway When linewrapping is disabled text in cells stay on one line keeping rows same height Enabling rowselection provides a checkbox in the first column that is fixed on a scrolling table Linewrapping disabled rowselection enabled Here linewrapping is enabled so text in cells flows into multiple lines Rowselection is disabled so theres no checkbox per row Linewrapping enabled rowselection disabled Table Linewrapping disabled rowselection disabled Linewrapping enabled rowselection enabled Row selection The video below visualises how bulk actions light blue bar appear when rows are selected The bulk actions are only possible when rowselection is enabled Small device considerations For smaller screens its worth deciding which columns to hide if any Aim at scrolling in only one direction vertical whenever possible In the example below the lines are clickable and all details can be provided in the object view instead of trying to get everything into the table If you find a bug or need a feature Create GitHub Issue"},{"title":"","href":"design/patterns/tabs.html","content":""},null,{"title":"Root Panels","href":"development/rootpanels/index.html","content":"Root Panels Root panels Root panels is a work in progress This is a developer preview The API markup or layout of this component might change significantly We can position Panel elements as direct children of the body to autogenerate labeled tabs in the ToolBar This will allow multiple Main to exist If the developers wants to reflect the selected tab in the URL for history support he must add some custom functionality to the onselect method of each individual Tab in the TopBar But this should be made easier see note below We should implement onselect as a configurable method on the TopBar API so that this becomes easier to setup The method couldpass the selected Tab andor selected index as an argument Panel Two A In this Panel the nested Main contains two additional Panel elements to autogenerate a TabBar the TabBar is shown at the top of the page Panel One Panel Three Panel Two B Chuck cow Tradeshift pork shoulder loin drumstick swine biltong pastrami fatback meatball ham rump boudin picanha Ground round beef ribs doner boudin brisket biltong tbone capicola Corned beef flank pancetta sirloin jowl meatball pork chop alcatra Landjaeger biltong pork chop alcatra spare ribs turducken strip steak bresaola shankle chicken pastrami doner salami brisket Ham hock biltong tbone salami sausage pork spare ribs beef flank pig Kevin meatloaf turducken short loin sausage spare ribs tongue ham hock leberkas ham strip steak pig jerky Tenderloin alcatra leberkas shoulder sirloin pancetta short ribs pastrami tbone tritip pork belly kevin Tenderloin filet mignon chicken spare ribs meatball capicola ham jerky swine bresaola pork chop ribeye cupim tbone bacon Pork belly tail swine ham hock alcatra pork chop shoulder pastrami spare ribs venison hamburger beef drumstick pancetta Kevin swine ham spare ribs strip steak andouille rump Pork chop rump filet mignon shankle pastrami ground round landjaeger ribeye shoulder strip steak chicken bresaola Swine turkey bresaola flank jerky salami bacon filet mignon Turducken jowl pork chop meatball pastrami swine ball tip leberkas Doner cow chicken rump swine flank salami Pork belly bacon tenderloin tongue cow tritip alcatra short ribs turducken chicken biltong drumstick meatball Drumstick frankfurter shank sausage andouille shankle Strip steak flank brisket ham pastrami shoulder hamburger chicken drumstick meatball tail Brisket drumstick meatball leberkas beef ribs Prosciutto bacon pork shoulder salami Meatloaf salami beef chuck biltong Flank sausage shoulder bresaola sirloin prosciutto boudin cupim strip steak andouille pancetta Landjaeger drumstick spare ribs salami venison picanha pork rump cupim andouille sirloin beef ribeye meatloaf Bacon short loin pork leberkas shank salami rump pig ribeye porchetta tail spare ribs Turducken short ribs prosciutto venison fatback sirloin beef strip steak rump shankle ground round Tenderloin picanha landjaeger beef ribs Drumstick ribeye prosciutto salami Tenderloin bacon spare ribs rump kielbasa Strip steak tongue bacon andouille meatloaf beef ribeye salami brisket pancetta short loin short ribs rump turducken Andouille turducken meatball prosciutto corned beef tbone Jerky shoulder andouille kielbasa tbone leberkas pork chop Turducken hamburger prosciutto ground round pork chop frankfurter jerky Tenderloin pastrami picanha doner short ribs ham hock short loin ground round shankle ham kevin capicola turkey brisket Jowl ribeye rump short ribs bacon ham tenderloin doner hamburger tbone sausage cupim turkey shankle short loin Bacon ipsum dolor amet boudin beef ribs landjaeger sausage pig turkey short loin pork loin ball tip chuck kevin doner shank flank Tradeshift kielbasa strip steak andouille chicken corned beef alcatra tritip sirloin pancetta brisket pork loin drumstick landjaeger ham hock Pork ball tip picanha drumstick jerky ham hock Venison meatloaf strip steak pork beef Pork chop sirloin ball tip spare ribs short loin porchetta capicola fatback leberkas drumstick turducken frankfurter Bacon ribeye turducken landjaeger corned beef capicola ground round Meatball pork chop spare ribs sirloin leberkas swine tritip ham hock pork loin brisket Filet mignon beef corned beef jerky pig alcatra ground round kielbasa Ham tenderloin beef jowl prosciutto Alcatra cow meatball beef ribs shoulder venison Tenderloin beef ribs jowl bresaola ball tip Ribeye pastrami venison porchetta chicken drumstick meatloaf boudin Beef ribs cow biltong salami meatball shankle fatback ribeye sirloin meatloaf strip steak turkey capicola bresaola cupim Rump corned beef alcatra cow salami shankle boudin brisket sausage ham hock landjaeger tbone picanha sirloin Prosciutto ham picanha chicken ham hock Alcatra sirloin beef tbone rump Jerky pork chop picanha andouille Rump boudin ham frankfurter tbone leberkas Tbone hamburger sirloin andouille tenderloin prosciutto tongue cupim shoulder meatloaf Ribeye filet mignon tbone short ribs jerky Strip steak pork loin spare ribs flank bacon sausage cow shank short ribs fatback Cupim chuck brisket beef ribs pork loin alcatra drumstick Pastrami meatball biltong alcatra fatback boudin short ribs drumstick chuck jerky turducken hamburger Venison cow sausage rump picanha turducken meatloaf shoulder strip steak jowl Chicken porchetta doner sirloin pig shank flank bacon rump corned beef Pastrami tenderloin jowl tbone doner drumstick pork chop shankle leberkas meatloaf ham hock pig Jerky ground round rump biltong tritip swine cupim corned beef picanha Cow chicken sausage tritip Jowl pastrami tail short ribs bresaola flank meatball tbone boudin sausage shoulder fatback andouille Frankfurter tail pancetta tritip pork meatball ham hock swine filet mignon andouille hamburger Sirloin alcatra picanha pastrami chuck ham jerky kielbasa tail boudin corned beef spare ribs brisket Drumstick fatback strip steak bacon brisket kevin pork ribeye hamburger Rump beef jowl drumstick ground round fatback salami frankfurter porchetta pig pork belly swine flank Pork loin corned beef shoulder landjaeger ham hock picanha ball tip Picanha pig cow landjaeger pastrami chuck tail Bresaola boudin frankfurter strip steak tbone pork belly shoulder brisket Ham jerky tenderloin short loin Spare ribs drumstick short loin pork loin Ham hock capicola jowl venison porchetta cupim spare ribs kevin tritip corned beef turkey tongue sirloin Boudin short loin alcatra frankfurter fatback spare ribs andouille tritip chicken capicola Chicken tongue jowl ground round corned beef alcatra ball tip meatloaf turducken jerky venison shank salami Cow beef cupim pork chop doner biltong kielbasa picanha ham tbone ball tip Jowl frankfurter ground round short ribs kevin leberkas sirloin shoulder pork loin boudin spare ribs picanha brisket pig beef Pork chop shank jerky cow pancetta short loin tail fatback pork belly tongue kevin Ground round pork chop beef short ribs ball tip cupim sirloin ham alcatra kevin Ball tip short ribs picanha alcatra kevin spare ribs rump shank ham Shankle pig shank turducken Turkey landjaeger ground round biltong Biltong rump frankfurter bacon chicken alcatra ham ribeye tongue Tongue filet mignon pig pork chop andouille shoulder tenderloin picanha sausage jowl brisket meatloaf Pastrami tongue swine bresaola picanha leberkas meatball chicken jerky tenderloin doner tbone pork chop Strip steak beef ribs venison porchetta sausage meatloaf hamburger Bacon spare ribs sausage porchetta prosciutto cupim meatloaf corned beef Andouille shankle tenderloin venison frankfurter rump cow ball tip pancetta hamburger Brisket alcatra bresaola doner flank shank Prosciutto salami venison frankfurter pastrami Porchetta jerky swine ham hock tritip shoulder pork loin turducken jowl Panel Three In this Panel we test that the SideBar is also working Panel One Panel Two "},{"title":"Get Started","href":"getstarted/index.html","content":"Get started This is a good starting point also for visual designers who prefer to work in HTML because the script will inject the stylesheet along with the fonts and icons etc edbmldeclareedbmlZ2dVzsb1asfunction edbml use strict var out edbmlout txt edbmlsafetext outhtml To get Tradeshift UI up and running on your page simply include tsjs in an appropriate version The latest version is txttsuiversion return outwrite UI components are initialized on the DOMContentLoaded event but this might change some day To make sure that all the components are initialized before you do something to them you can wrap you code in a callback like this tsuireadyfunction var component tsuigetelement componentdosomething Before DOMContentLoaded the callback will be executed later After DOMContentLoaded the callback will execute immedeately You can perhaps make it easier for yourself by kickstarting your app with a tsuiready callback because then you wontt have to worry about it later on tsuireadyfunction boostrapeverything Before we begin youll need to mark up your page with the basic layout If you find a bug or need a feature Create GitHub Issue"},{"title":"Layout","href":"getstarted/layout/index.html","content":"Layout This is the minimum viable HTML boilerplate for UI components to work out You may want to tweak the viewport meta tag but this is a good starting point Layout Main content TopBar The page should have a TopBar even if you dont plan to use it Thats because the topbar is always visible in mobile layout where it functions to toggle the main navigation menu Main The Main draws the scrollbar now that body overflow is hidden This setup will let us use absolute position to emulate fixed position which doesnt work right inside iframes on mobile devices MainContent The MainContent element should contain more or less everything your app has to show Asides If youre using Asides its important to place them outside Main like this Main content Aside content With this in mind you are ready to start using components If you find a bug or need a feature Create GitHub Issue"},{"title":"Basic rules","href":"getstarted/rules/index.html","content":"Basic rules UI components would like to assume ownership of The datats HTML attribute All HTML attributes that start with datats dot All HTML attributes that start with datats dash All CSS classnames that start with ts dash The global namespace object tsui Rule number one is to not use ts prefixed CSS classnames in your app UX designers can continue reading the Design Principles while developers may skip directly to the UI Components section If you are new to Tradeshift you should probably read both If you find a bug or need a feature Create GitHub Issue"},{"title":"Usage","href":"getstarted/usage/index.html","content":"Basic usage You will use any combination of HTML attributes CSS classnames and JavaScript interfaces to deal with the different components Most components are used simply by adding the datats attribute to elements The framework will recognize this attribute and add behavior and styling Config attributes Additional attributes may be used to configure the component By convention these will be prefixed with datats including the dot The datatsopen attribute would for example open the aside JS interface The component may also expose a JavaScript API For example the Aside can be opened with a method call instead of an attribute You can get hold of the implementation using tsuiget which takes an element as argument var myelement documentquerySelectormyaside var component tsuigetmyelement consolelogcomponent object tsuiAsideSpirit componentopen APIonly components Components that embody more complex behavior will usually be dealt with through a pure JavaScript API so without writing markup This will come in handy when we decide to change the complex behavior at a later stage tsuiDatePicker title Your Birthday value 19730326 open When making apps with UI components theres a few basic rules we would like you to observe If you find a bug or need a feature Create GitHub Issue"},{"title":"Tradeshift UI","href":"index.html","content":"Tradeshift UI includes menuhtml svgicons menujson If you find a bug or need a feature Create GitHub Issue"},{"title":"Tradeshift UI","href":"intro/index.html","content":"Tradeshift UI Tradeshift UI UI components range from simple buttons and icons to fancy datepickers and dropdown menus The target audience for Tradeshift UI is both developers and designers For Developers For Tradeshift apps the UI components are built to allow for consistent styling and experiences across internal apps For thirdparties the UI components are designed to bring visual consistency with internal applications as part of the Tradeshift platform Get Started Everything you need to use Tradeshift UI Components in your app Components Overview The building blocks that Tradeshift apps are made of Great Appendix Colors typography bonus features and notes on responsive design For Designers For our designers the UI components are designed to allow rapid prototyping without duplicating efforts between prototypes As a result of being standardized they will also act as a single point in Tradeshift for designers to revise UI components Design Guidelines The foundational principles and concepts of the Tradeshift UX Design Patterns Recurring solutions to challenges youll encounter when designing a Tradeshift app UI Copy Strong copy is essential we give you this guide to help you have great copy with your great designs"},null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,{"title":"Search","href":"search/index.html","content":"If you find a bug or need a feature Create GitHub Issue"},null] \ No newline at end of file +[{"title":"Testing","href":"TEST.html","content":"Hell World If you find a bug or need a feature Create GitHub Issue"},{"title":"Automagic Focus","href":"appendix/autofocus/index.html","content":"Automagic focus On this page weve added a yellow outline to the focused element Keyboard support is always a work in progress but we have a system to ensure that something is in theory always focused Note that there is no default focus but you can set the default focus with the HTML autofocus attribute In Notifications and Asides well always attempt to focus something even if we cant find any element with the autofocus attribute Click the buttons to see Open the Notification Open the Aside TODO Note about focus on mobile device Aside content Open next aside Open next aside Thanks now close them It appears we have a bug If you do click that button the focus will be lost But you can try to close them one at a time by clicking the X in the corner If you find a bug or need a feature Create GitHub Issue"},null,{"title":"Automated Layout","href":"appendix/autolayout/index.html","content":"Automated Layout var LayoutModel tsuiModelextend topBar false toolBarBefore false toolBarAfter false sideBarBefore false sideBarAfter false new LayoutModeloutput tsform margintop 22px hack for empty SPAN labelspan fontweight 300 edbmldeclareedbmliSNtu1asfunction edbml use strict var out edbmlout set edbmlset txt edbmlsafetext val edbmlsafeattr layout edbmlinputLayoutModel if layouttopBar outhtml if layoutsideBarBefore outhtml SideBar content Optional SideBar footer if layouttoolBarBefore outhtml outhtml Automated layout We donapost have a lot of layouts yet but the page will automatically transform into a classic three column layout with fixed headers and footer as certain components are added You can toggle these components in the checklist function checkboxtext prop localhost if localhost locationhostname localhost outhtml var 1 setfunctionvalue checked layoutprop checked this outhtml txttext checkboxTopBar topBar checkboxToolBar before Main DEPRECATED toolBarBefore true checkboxToolBar after Main DEPRECATED toolBarAfter true checkboxSideBar before Main sideBarBefore checkboxSideBar after Main sideBarAfter outhtml TODO Save this page in mobile breakpoint if layouttoolBarAfter outhtml if layoutsideBarAfter outhtml SideBar content Optional SideBar footer return outwrite withInstructions input name layout type LayoutModel If you find a bug or need a feature Create GitHub Issue"},{"title":"Colors","href":"appendix/colors/index.html","content":"Colors Colors Here you can see a list of colors you can use in Tradeshift apps edbmldeclareedbml1JJU8I0asfunction edbml use strict var out edbmlout att edbmlatt txt edbmlsafetext val edbmlsafeattr var colors tsblack rgb303030 tswhite rgb255255255 tsdarkdarker rgb333333 tsdarkdark rgb434343 tsdark rgb535353 tsdarklite rgb636363 tsdarkliter rgb737373 tsmediumdarkest rgb979797 tsmediumdarker rgb107107107 tsmediumdark rgb117117117 tsmedium rgb127127127 tsmediumlite rgb137137137 tsmediumliter rgb147147147 tsmediumlitest rgb175175175 tslitedarker rgb205205205 tslitedark rgb215215215 tslite rgb225225225 tslitelite rgb235235235 tsliteliter rgb245245245 tsgreen rgb11417772 tsgreendark rgb9415752 tsgreendarker rgb7413732 tsgreenlite rgb13419792 tsgreentext tswhite tslitegreen rgb178215130 tsdarkgreen rgb248463 tsblue rgb32160233 tsbluedark rgb12140213 tsbluedarker rgb0120193 tsbluelite rgb43180253 tsblueliter rgb88184239 tsbluetext tswhite tsliteblue rgb236247253 tslitebluedark rgb220241253 tsdustblue rgb5499117 tsdarkblue rgb246384 tsred rgb19100 tsreddark rgb17100 tsreddarker rgb15100 tsredlite rgb23100 tsredtext tswhite tsdarkred rgb2333232 tsdarkredlite rgb248229229 tsdarkredtext tswhite tsyellow rgb253254213 tsyellowdark rgb244242201 tsyellowtext rgb12711572 tsorangeliter rgb250 236 217 tsorangelite rgb245 224 184 tsorange rgb230 153 0 tsorangedark rgb209 91 0 tsorangedarker rgb66 40 0 tspurple rgb14852200 tspurpledark rgb12845173 tspurpledarker rgb10825153 tspurplelite rgb16658224 tspurpletext tswhite colorsforEachfunctioncolorSet outhtml for var colorName in colorSet var colorCode colorSetcolorName outhtml commat txtcolorName txtcolorCode outhtml return outwrite "},{"title":"Appendix","href":"appendix/index.html","content":"Appendix You can make great Tradeshift apps by studying these pages that didnt fit elsewhere in the menu structure Implement responsive design with some handy CSS classnames Get an overview of the color scheme used in Tradeshift See some basic examples of the general typography Learn the primitive dialect of Markdown that we use Observe the principle of automated layout in action Be aware that UI components will attempt to manage the focus If you find a bug or need a feature Create GitHub Issue"},null,{"title":"Markdown","href":"appendix/markdown/index.html","content":"Markdown If you find a bug or need a feature Create GitHub Issue"},null,null,{"title":"Typography","href":"appendix/typo/index.html","content":"Typography Heres a very basic overview of the typography used in Tradeshift Apps H1fontsize 36px tsfontsizexxbig H2fontsize 24px tsfontsizexbig H3fontsize 18px tsfontsizebig Normal paragraph of textfontsize 14px tsfontsize Unordered List Ordered List If you find a bug or need a feature Create GitHub Issue"},null,null,null,null,null,null,null,null,{"title":"API-only Components","href":"components/api-only.html","content":"APIonly components These components will insert themselves into the DOM and generally dont come with a HTML API Some of them are known to affect the general page layout TopBar The TopBar provides tabs for navigation and buttons for contextual actions Beware that this API will be replaced be the tsuiHeader in a future release tsuiTopBarbuttons label Button type tsprimary label Button type tssecondary label Button onclick function consolelogClicked tsuiTopBarbuttons label Button type tsprimary label Button type tssecondary label Button onclick function consolelogClicked Main TabBar The Main TabBar provides second level tabbed navigation Beware that this API will be replaced be the tsuiHeader in a future release tsuiTabBartabs label Tab One label Tab Two label Tab Three onselect function consolelogSelected tsuiTabBartabs label Tab One label Tab Two label Tab Three onselect function consolelogSelected Main ToolBar The Main ToolBar features a Search and even more buttons for contextual actions Beware that this API will be replaced be the tsuiHeader in a future release tsuiToolBarbuttons label Button type tsprimary label Button type tssecondary label Button onclick function consolelogClicked search info Search amongst the things onsearch functionvalue consolelogvalue tsuiToolBarbuttons label Button type tsprimary label Button type tssecondary label Button onclick function consolelogClicked search info Search amongst the things onsearch functionvalue consolelogvalue Footer The Footer is positioned below the Main area where it usually functions to display some buttons But the Footer also supports actions which are reserved for working with selected objects of any kind as well as a Pager and a dedicated Collaboration button tsuiFooterbuttons label Button type tsprimary label Button type tssecondary label Button onclick consolelogButton clicked actions label Action icon tsiconfollowed label Action icon tsiconfavorites label Action icon tsiconcode onclick consolelogAction clicked statusHello World tsuiFooterbuttons label Button type tsprimary label Button type tssecondary label Button onclick consolelogButton clicked actions label Action icon tsiconfollowed label Action icon tsiconfavorites label Action icon tsiconcode onclick consolelogAction clicked statusHello World DatePicker A easy way to select dates tsuiDatePicker title Your Birthday value 19840523 min 19840101 max 19851224 onselect functiondate tsuiNotificationsuccessdate selected thisclose onclosed function thisdispose open tsuiDatePicker title Your Birthday value 19840523 min 19840101 max 19851224 onselect functiondate tsuiNotificationsuccessdate selected thisclose onclosed function thisdispose open Dialog Works much like the JavaScript confirm method tsuiDialogconfirmShow the Warning dialog Show It Nope onaccept function tsuiDialogwarningShow the Danger dialog Of Course onaccept function tsuiDialogdangerThat could be dangerous Got it tsuiDialogconfirmShow the Warning dialog Show It Nope onaccept function tsuiDialogwarningShow the Danger dialog Of Course onaccept function tsuiDialogdangerThat could be dangerous Got it Notification Themed variants of the JavaScript alert method tsuiNotificationsuccessNotificationsuccess tsuiNotificationinfoNotificationinfo tsuiNotificationwarningNotificationwarning tsuiNotificationerrorNotificationerror tsuiNotificationsuccessNotificationsuccess tsuiNotificationinfoNotificationinfo tsuiNotificationwarningNotificationwarning tsuiNotificationerrorNotificationerror Note A nice way to inform the user about something in general This is not for status messages The Note attaches to the top of the page so you will have to scroll back up tsuiNote icon tsiconheart text This is the Note Thanks for scrolling up onclose function tsuiNotificationsuccessThe Note is gone tsuiNote icon tsiconheart text This is the Note Thanks for scrolling up onclose function tsuiNotificationsuccessThe Note is gone UserCard Show some details about a user tsuiUserCard id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Wired Earp image assetswiredearppng title EDB Programmer role Gentleman Spy email jmotradeshiftcom company Tradeshift companyUrl httptradeshiftcom open tsuiUserCard id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Wired Earp image assetswiredearppng title EDB Programmer role Gentleman Spy email jmotradeshiftcom company Tradeshift companyUrl httptradeshiftcom open If you find a bug or need a feature Create GitHub Issue"},{"title":"Aside HTML","href":"components/asides/index.html","content":"Aside Sidepanel used for small user interactions such as selecting a date The Aside component must be created with a child component Panel Aside content Aside content You can create the Aside wherever you like just make sure that its positioned outside of the Main element when it opens Main content Aside content Main content Aside content Adding a header The datatstitle attribute configures the Aside with a nice header Aside content Aside content You can color the header by assigning any of the classnames tsbgblue tsbggreen tsbgred and tsbgpurple to the Aside element itself Opening the aside The datatsopen attribute can be flipped to toggle the Aside Aside content Aside content Lets try that with jQuery myasideattrdatatsopen true myasideattrdatatsopen true Adding some tabs If an Aside contains more than one Panel we will automatically create a TabBar to switch between the panels like in this example Aside content Aside content Aside content Aside content The tabs can also be created programatically In that case the panel switching mechanism must be implemented manually somehow tsuigetaside3 aside asidetabs label Tab 1 onselect function consolelogPanel one label Tab 2 onselect function consolelogPanel two open tsuigetaside3 aside asidetabs label Tab 1 onselect function consolelogPanel one label Tab 2 onselect function consolelogPanel two open You can also mix the two approaches to dynamically update tabs that were created with Panel elements This will for example assign an onselect callback to the third tab tsuigetmyaside aside var tabs asidetabs tabs2onselect function consolelogselected tsuigetmyaside aside var tabs asidetabs tabs2onselect function consolelogselected To remove all dynamically created tabs you can simply clear the tab collection tsuigetmyaside aside asidetabsclear tsuigetmyaside aside asidetabsclear Adding some buttons Its common for Asides to show a group of buttons usually following a set of form fields To make sure that they always look the same the certified way to add this group of buttons is via a Buttons menu form fields here Submit Changes Cancel Everything form fields here Submit Changes Cancel Everything Showing the spinner The datatsbusy attribute can be set to show the spinner Aside content Aside content Lets try that with jQuery var aside myaside asideattrdatatsbusy Loading asideattrdatatsopen true setTimeoutfunction asideattrdatatsbusy setTimeoutfunction asideattrdatatsopen false 500 1500 var aside myaside asideattrdatatsbusy Loading asideattrdatatsopen true setTimeoutfunction asideattrdatatsbusy setTimeoutfunction asideattrdatatsopen false 500 1500 Tracking the state You can setup inline callbacks to be invoked when the aside changes state using one of onopen onopened onclose and onclosed You can also do this with event listeners if you like Aside content Aside content Stacking Asides Asides will automatically stack themselves whenever new asides open The old Asides will slide elegantly to the right The new Aside will float the top of the zindex Bacon ipsum dolor sit plsesnack jerky pork belly short loin sausage andouille kevin capicola ham hamburger doner Shank prosciutto flank kevin ribeye short ribs swine ham pork porchetta spare ribs kielbasa beef ribs Prosciutto pancetta shank boudin Corned beef shoulder capicola turducken prosciutto pork belly sirloin shankle brisket chuck leberkas tail beef Sirloin meatloaf pastrami beef ribs Ball tip pastrami landjaeger brisket Tradeshift strip steak short loin pancetta meatball corned beef tenderloin beef ribs spare ribs Tradeshift sausage strip steak ham ribeye pork loin meatball turkey corned beef shoulder Leberkas jerky sirloin boudin turducken ham hock pastrami Doner pig boudin sausage ball tip leberkas ground round beef jowl kielbasa tongue shankle spare ribs tail shoulder Fatback pork kielbasa ham doner pig short loin short ribs pancetta Pancetta jerky biltong short loin capicola beef Pork belly strip steak venison brisket shoulder beef filet mignon shank tenderloin tritip ground round shankle cow Tradeshift salami burger mit invoice pastrami shankle venison meatball pork belly capicola ribeye sirloin doner Aside Tail kielbasa beef ribs landjaeger pork belly Tbone pig andouille doner ham sirloin short ribs meatloaf salami strip steak tenderloin short loin tritip pork loin Pastrami jowl sirloin kevin jerky filet mignon bacon pork chop brisket pancetta Spare ribs ground round pork belly pork chop doner swine fatback bresaola Picanha beef ribs burgdoggen bacon sausage rump Porchetta turkey ribeye tenderloin landjaeger spare ribs strip steak pork belly tbone Tenderloin tbone ham doner corned beef chuck fatback ground round short ribs tritip Landjaeger ribeye brisket boudin tongue pork kevin frankfurter Swine capicola filet mignon cow spare ribs ribeye salami sausage porchetta hamburger short ribs corned beef Open next aside Open next aside Thanks now close them If you find a bug or need a feature Create GitHub Issue"},{"title":"Aside JS","href":"components/asides/js.html","content":"Asides JS You can get a hold of the Aside component and control it with JavaScript tsuigetmyaside aside you can pass an element instead of an ID asideopen asideclose asidetoggle asidetitleUpdated title Tracking with methods You can overwrite the methods onopen onopened onclose and onclosed to do something whenever the aside changes state asideonopen function consolelogAside will open If you return false in methods onopen and onclose the aside will respect that Tracking with events You can also monitor the asides with DOM event listeners function debuge consolelogetype etarget documentaddEventListenertsopen debug documentaddEventListenertsopened debug documentaddEventListenertsclose debug documentaddEventListenertsclosed debug The events tsopen and tsclose can be blocked with epreventDefault to prevent the aside from changing state If you find a bug or need a feature Create GitHub Issue"},{"title":"","href":"components/asides/tabs.html","content":""},null,null,null,null,{"title":"StatusBar","href":"components/bars/statusbar-DEPRECATED.html","content":"Main StatusBar is deprecated This component is deprecated in favor of the Footer In a future release the TopBar and TabBar and ToolBar will be collected in the equivalent Header You can still use the StatusBar as an inline component Although the StatusBar can display status messages and features a Pager its perfectly alright to use it just to show some buttons You can show a status message with basic Markdown support tsuiStatusBarmessage The status message supports bold and italic text tsuiStatusBarmessage The status message supports bold and italic text If you call linkable you can also some links in the message Beware of phishing tsuiStatusBarlinkablemessage Please visit Tradeshifthttpwwwtradeshiftcom tsuiStatusBarlinkablemessage Please visit Tradeshifthttpwwwtradeshiftcom You can pass a callback function to be invoked whenever a link is clicked tsuiStatusBarlinkablefunction onclickurl tsuiNotificationsuccessurl thismessageThanks messagePlease click the linkThe URL can be any string tsuiStatusBarlinkablefunction onclickurl tsuiNotificationsuccessurl thismessageThanks messagePlease click the linkThe URL can be any string StatusBarbuttons Add buttons to the StatusBar with the buttons method This both sets and gets If you omit the argument youll get the current buttons jQuery style tsuiStatusBarbuttons label Primary type tsprimary label Secondary type tssecondary label Tertiary One label Tertiary Two tsuiStatusBarbuttons label Primary type tsprimary label Secondary type tssecondary label Tertiary One label Tertiary Two You can use array methods like push pop shift unshift splice reverse and so on to manage buttons Just note that the buttons length is readonly The buttons type property works like the CSS class for a regular Button The StatusBar will automatically sort all buttons from primary to tertiary If theres more than one tertiary button these will be pushed to an Aside In the mobile breakpoint all the buttons will be pushed to an Aside Buttons wont actually do anything unless you define the onclick method tsuiStatusBarbuttonssplice0 1 label Click me type tsprimary onclick function thislabel Thanks tsuiStatusBarbuttonssplice0 1 label Click me type tsprimary onclick function thislabel Thanks Fortunately you can always change what happens when a button gets clicked tsuiStatusBarbuttonsforEachfunctionbutton index buttonlabel Button index 1 buttononclick function tsuiNotificationsuccessthislabel tsuiStatusBarbuttonsforEachfunctionbutton index buttonlabel Button index 1 buttononclick function tsuiNotificationsuccessthislabel Query buttons You can locate buttons by index in the buttons collection But since this isnt likely to match the order in which they appear on screen its easier to give the buttons an id and find them using buttonsget var buttons tsuiStatusBarbuttons buttonspush id examplebutton var button buttonsgetexamplebutton buttonlabel My Button buttontype tssecondary var buttons tsuiStatusBarbuttons buttonspush id examplebutton var button buttonsgetexamplebutton buttonlabel My Button buttontype tssecondary Hide buttons You can hide and show buttons You can also toggle visible tsuiStatusBarbuttonsforEachfunctionbutton ifbuttonvisible buttonhide else buttonshow tsuiStatusBarbuttonsforEachfunctionbutton ifbuttonvisible buttonhide else buttonshow Disable buttons You can disable and enable buttons You can also toggle disabled tsuiStatusBarbuttonsforEachfunctionbutton ifbuttondisabled buttonenable else buttondisable tsuiStatusBarbuttonsforEachfunctionbutton ifbuttondisabled buttonenable else buttondisable Busy buttons We can display a temporary progress indicator with the busy and done methods var button tsuiStatusBarbuttons0 buttonbusy setTimeoutfunction buttondone 1000 var button tsuiStatusBarbuttons0 buttonbusy setTimeoutfunction buttondone 1000 The busy method supports an optional status message var button tsuiStatusBarbuttons0 buttonbusyMaking progress setTimeoutfunction buttondone 1000 var button tsuiStatusBarbuttons0 buttonbusyMaking progress setTimeoutfunction buttondone 1000 Button groups You can also group buttons in arrays to create button groups that look like this tsuiStatusBarbuttons label Normal label Normal label Accept type tsprimary label Reject type tsdanger tsuiStatusBarbuttons label Normal label Normal label Accept type tsprimary label Reject type tsdanger You can of course also create grouped buttons with icons instead of text var group tsuiStatusBarbuttons2 grouppush icon tsiconother type tssecondary var group tsuiStatusBarbuttons2 grouppush icon tsiconother type tssecondary Heres a summary of the buttons collection and button model StatusBarpager You can initialize a Pager in the StatusBar tsuiStatusBarpager pages 23 page 0 onselect functionpage consolelogpage tsuiStatusBarpager pages 23 page 0 onselect functionpage consolelogpage To make room for the Pager and to make it look nice centeraligned any potential buttons in the StatusBar will be moved into a menu Note that even primary buttons will be hidden when the StatusBar features a Pager TODO Explain how the statusbar behaves in mobile view Also we might need to split long status messages into two lines when the window is resizing For now well just pretend that all users have desktopsized screens Inline Statusbar The responsive StatusBar is a work in progress This is a dev preview Assign datatsStatusBar to a footer or menu to initialize it as a StatusBar Another attribute datatsmessage displays the message The StatusBar has no default outline so weve fitted ours with a dropshadow In your app any such outlining should be done under consideration of the neighboring elements You can get a hold of the component using a CSS selector and call any of the methods weve seen applicable to the Main ToolBar Notice what happens when we add content tsuigetmystatusbar statusbar statusbarbuttons label One type tsprimary label Two type tssecondary label Three pager pages 23 messageThe layout has changed tsuigetmystatusbar statusbar statusbarbuttons label One type tsprimary label Two type tssecondary label Three pager pages 23 messageThe layout has changed Because there is limited horizontal space available the StatusBar has snapped into a layout that is optimized for mobile phones The exact layout depends on the features you enable but you can in any case intercept this change with the onlayout callback var statusbar tsuigetmystatusbar statusbaronlayout function thismessageThe layout has changed again statusbarpagernull just to show that it works var statusbar tsuigetmystatusbar statusbaronlayout function thismessageThe layout has changed again statusbarpagernull just to show that it works This is a work in progress If you find a bug or need a feature Create GitHub Issue"},{"title":"TabBar","href":"components/bars/tabbar.html","content":"Main TabBar Second level navigation is in danger of becoming deprecated so please be cautious with this design pattern We can initialize the TabBar tabs with the the tabs method tsuiTabBartabs label Main TabBar label Inline TabBar but since the page already has tabs we will instead append a new tab to the existing collection If you omit the argument youll get the current tabs jQuery style var tabs tsuiTabBartabs tabspush label Bonus Tab onselect function var text thislabel selected tsuiNotificationsuccesstext var tabs tsuiTabBartabs tabspush label Bonus Tab onselect function var text thislabel selected tsuiNotificationsuccesstext You can use array methods like push pop shift unshift splice and so on to manage tabs just note that the tabs length is a readonly property Also note that tabs dont do anything by default so what happens at onselect is completely up to you Updating tabs We can at any time change what happens when a tab gets selected We can also change the tab label if we like although maybe this would be confusing for the user var tabs tsuiTabBartabs tabs2label Choose Me tabs2onselect function thislabel Thanks var tabs tsuiTabBartabs tabs2label Choose Me tabs2onselect function thislabel Thanks Selecting tabs We can programatically select a tab using one of these approaches tsuiTabBartabs2select tsuiTabBartabsselectedIndex 0 Querying tabs This will all become a lot easier if we give all the tabs an id and use tabsget var tabs tsuiTabBartabs tabssplice2 0 label Example Tab id exampletab tabsgetexampletabselect var tabs tsuiTabBartabs tabssplice2 0 label Example Tab id exampletab tabsgetexampletabselect Tabs icons You can add a tab with an icon if somehow that tab is special tsuiTabBartabspush label Icon Tab icon tsicontodo tsuiTabBartabspush label Icon Tab icon tsicontodo Tab counters You can add a counter to the tabs for whatever reason you like tsuiTabBartabsforEachfunctiontab tabcounter MathceilMathrandom 10 tsuiTabBartabsforEachfunctiontab tabcounter MathceilMathrandom 10 When the counter reaches zero it disappears tsuiTabBartabsforEachfunctiontab tabcounter tsuiTabBartabsforEachfunctiontab tabcounter Closeable tabs You can create closeable tabs but note that the tab must be selected before it can be closed You can return false in the onclose method to prevent the tab from closing if this would otherwise cause data loss tsuiTabBartabspush label Closeable Tab closeable true selected true onclose function tsuiNotificationsuccessthislabel closed tsuiTabBartabspush label Closeable Tab closeable true selected true onclose function tsuiNotificationsuccessthislabel closed NewTab button You can allow the user to create new tabs via a special button as seen in popular browsers Note that the button just triggers a callback and that the new tab must be created manually In the example below the selected property also selects the tab var tabs tsuiTabBartabs tabsshowNewfunction onclick tabspush label My New Tab selected true var tabs tsuiTabBartabs tabsshowNewfunction onclick tabspush label My New Tab selected true If you regret this later on you can also hide the button tsuiTabBartabshideNew tsuiTabBartabshideNew Heres a summary of the tabs collection and tab model TabBarbuttons Its perfectly alright to add buttons to the TabBar either to avoid wasting space on a separate ToolBar or because the buttons will affect content in all the tabs tsuiTabBarbuttons label One type tsprimary label Two type tssecondary label Three tsuiTabBarbuttons label One type tsprimary label Two type tssecondary label Three If the buttons affect the selected tab only remember to clear the buttons when a new tab is selected tsuiTabBarbuttonsclear tsuiTabBarbuttonsclear Heres a summary of the buttons collection and button model Inline TabBar TabBars can be positioned anywhere on the page Assign datatsTabBar to a header or nav to initialize it as a TabBar All features are controlled through a JavaScript API You can get a hold of the component using a CSS selector and call any of the methods weve seen applicable to the Main TabBar tsuigetmytabbar tabbar tabbartabs label One label Two label Three tsuigetmytabbar tabbar tabbartabs label One label Two label Three Heres an overview of the inline TabBar component If you find a bug or need a feature Create GitHub Issue"},{"title":"","href":"components/bars/tabs.html","content":""},{"title":"ToolBar","href":"components/bars/toolbar.html","content":"Main ToolBar Besides buttons for contextual actions the ToolBar also features a Search Beware that this API will be replaced be the tsuiHeader in a future release Before we begin we may consider adding a descriptive title to the ToolBar tsuiToolBartitleMy ToolBar tsuiToolBartitleMy ToolBar ToolBarbuttons Add buttons to the ToolBar with the buttons method This both sets and gets If you omit the argument youll get the current buttons jQuery style tsuiToolBarbuttons label Primary type tsprimary label Secondary type tssecondary label Tertiary One label Tertiary Two tsuiToolBarbuttons label Primary type tsprimary label Secondary type tssecondary label Tertiary One label Tertiary Two You can use array methods like push pop shift unshift splice reverse and so on to manage buttons Just note that the buttons length is readonly The buttons type property works like the CSS class for a regular Button The ToolBar will automatically sort all buttons from primary to tertiary If theres more than one tertiary button these will be pushed to an Aside In the mobile breakpoint all the buttons will be pushed to an Aside Buttons wont actually do anything unless you define the onclick method tsuiToolBarbuttonssplice0 1 label Click me type tsprimary onclick function thislabel Thanks tsuiToolBarbuttonssplice0 1 label Click me type tsprimary onclick function thislabel Thanks Fortunately you can always change what happens when a button gets clicked tsuiToolBarbuttonsforEachfunctionbutton index buttonlabel Button index 1 buttononclick function tsuiNotificationsuccessthislabel tsuiToolBarbuttonsforEachfunctionbutton index buttonlabel Button index 1 buttononclick function tsuiNotificationsuccessthislabel Query buttons You can locate buttons by index in the buttons collection But since this isnt likely to match the order in which they appear on screen its easier to give the buttons an id and find them using buttonsget var buttons tsuiToolBarbuttons buttonspush id examplebutton var button buttonsgetexamplebutton buttonlabel My Button buttontype tssecondary var buttons tsuiToolBarbuttons buttonspush id examplebutton var button buttonsgetexamplebutton buttonlabel My Button buttontype tssecondary Hide buttons You can hide and show buttons You can also toggle visible tsuiToolBarbuttonsforEachfunctionbutton ifbuttonvisible buttonhide else buttonshow tsuiToolBarbuttonsforEachfunctionbutton ifbuttonvisible buttonhide else buttonshow Disable buttons You can disable and enable buttons You can also toggle disabled tsuiToolBarbuttonsforEachfunctionbutton ifbuttondisabled buttonenable else buttondisable tsuiToolBarbuttonsforEachfunctionbutton ifbuttondisabled buttonenable else buttondisable Busy buttons We can display a temporary progress indicator with the busy and done methods var button tsuiToolBarbuttons0 buttonbusy setTimeoutfunction buttondone 1000 var button tsuiToolBarbuttons0 buttonbusy setTimeoutfunction buttondone 1000 The busy method supports an optional status message var button tsuiToolBarbuttons0 buttonbusyMaking progress setTimeoutfunction buttondone 1000 var button tsuiToolBarbuttons0 buttonbusyMaking progress setTimeoutfunction buttondone 1000 Button groups You can also group buttons in arrays to create button groups that look like this tsuiToolBarbuttons label Normal label Normal label Accept type tsprimary label Reject type tsdanger tsuiToolBarbuttons label Normal label Normal label Accept type tsprimary label Reject type tsdanger You can of course also create grouped buttons with icons instead of text var group tsuiToolBarbuttons2 grouppush icon tsiconother type tssecondary var group tsuiToolBarbuttons2 grouppush icon tsiconother type tssecondary Heres a summary of the buttons collection and button model ToolBarsearch Youll get a dedicated search field by passing an object to the search method tsuiToolBarsearch onsearch functionvalue tsuiNotificationsuccessvalue Search cleared tsuiToolBarsearch onsearch functionvalue tsuiNotificationsuccessvalue Search cleared The search field expands when the field is focused by the user or whenever theres a nonempty value in the field You can change the value like this var search tsuiToolBarsearch searchvalue Hello world var search tsuiToolBarsearch searchvalue Hello world Search callbacks The onsearch callback gets invoked when when the user presses ENTER var search tsuiToolBarsearch searchvalue Press ENTER here searchonsearch functionvalue tsuiNotificationsuccessvalue Search cleared var search tsuiToolBarsearch searchvalue Press ENTER here searchonsearch functionvalue tsuiNotificationsuccessvalue Search cleared If defined the onidle method gets called whenever the user pauses typing var search tsuiToolBarsearch searchvalue Try it now searchonidle functionvalue tsuiNotificationsuccessvalue var search tsuiToolBarsearch searchvalue Try it now searchonidle functionvalue tsuiNotificationsuccessvalue The onidle method may also be called when the field loses focus The idletime property controls the timeout value default is 500 milliseconds Search info The info property doubles as both the placeholder when the field is expanded and the title or tooltip when the field is collapsed var search tsuiToolBarsearch searchinfo Search amongst the things searchvalue collapse the field var search tsuiToolBarsearch searchinfo Search amongst the things searchvalue collapse the field Search flex You can flex the search field to make it stretch the available width of the ToolBar In that case it will remain expanded even when theres no default value tsuiToolBarsearch tip Flex all the way flex 1 buttons label No Flex type tsprimary tsuiToolBarsearch tip Flex all the way flex 1 buttons label No Flex type tsprimary You can also assign flex to buttons although that has little practical value In the future we may provide a more advanced distribution scheme Thats why we use a number instead of a boolean but you should always use 1 for now Here an overview of the properties and methods of the Search model and heres a final overview of the Main ToolBar methods Inline ToolBar ToolBars can be positioned anywhere on the page Assign datatsToolBar to a header or menu to initialize it as a ToolBar Another attribute datatstitle assigns a default title to the ToolBar The ToolBar has no default outline so weve fitted ours with a dropshadow In your app any such outlining should be done under consideration of the neighboring elements You can get a hold of the component using a CSS selector and call any of the methods weve seen applicable to the Main ToolBar tsuigetmytoolbar toolbar toolbarbuttons label One type tsprimary label Two type tssecondary label Three tsuigetmytoolbar toolbar toolbarbuttons label One type tsprimary label Two type tssecondary label Three The micro method may come in handy to make the ToolBar somewhat smaller In the HTML you can also assign the CSS classname tsmicro for the same effect tsuigetmytoolbarmicro tsuigetmytoolbarmicro The ToolBar will economize horizonatal space by collecting multiple tertiaray buttons in a menu when you Run This Code you may need to scroll the page back up to see it tsuigetmytoolbar toolbar toolbarbuttonspush label Four label Five label Six tsuigetmytoolbar toolbar toolbarbuttonspush label Four label Five label Six If you are absolutely certain that your buttons will fit in all supported languages you can disable this behavior with the uncompact method tsuigetmytoolbaruncompact tsuigetmytoolbaruncompact Heres an overview of the inline ToolBar component If you find a bug or need a feature Create GitHub Issue"},{"title":"TopBar","href":"components/bars/topbar.html","content":"TopBar Provides tabs for navigation and buttons for contextual actions Beware that this API will be replaced be the tsuiHeader in a future release If you plan to make use of the TopBar we suggest that you give it a descriptive title tsuiTopBartitleMy App tsuiTopBartitleMy App because even when the title is hidden by the tabs like on this page it will become visible when you resize to mobile breakpoint The title also functions to show the TopBar on page load so that it doesnt suddenly appear when you add buttons later TopBartabs We can initialize the TopBar tabs with the the tabs method tsuiTopBartabs label Overview label TopBar label TabBar label ToolBar label StatusBar but since the page already has tabs we will instead append a new tab to the existing collection If you omit the argument youll get the current tabs jQuery style var tabs tsuiTopBartabs tabspush label Bonus Tab onselect function var text thislabel selected tsuiNotificationsuccesstext var tabs tsuiTopBartabs tabspush label Bonus Tab onselect function var text thislabel selected tsuiNotificationsuccesstext You can use array methods like push pop shift unshift splice and so on to manage tabs just note that the tabs length is a readonly property Also note that tabs dont do anything by default so what happens at onselect is completely up to you Updating tabs We can at any time change what happens when a tab gets selected We can also change the tab label if we like although maybe this would be confusing for the user var tabs tsuiTopBartabs tabs4label Choose Me tabs4onselect function thislabel Thanks var tabs tsuiTopBartabs tabs4label Choose Me tabs4onselect function thislabel Thanks Selecting tabs We can programatically select a tab using one of these approaches tsuiTopBartabs4select tsuiTopBartabsselectedIndex 1 Querying tabs This will all become a lot easier if we give all the tabs an id and use tabsget var tabs tsuiTopBartabs tabssplice4 0 label Example Tab id exampletab tabsgetexampletabselect var tabs tsuiTopBartabs tabssplice4 0 label Example Tab id exampletab tabsgetexampletabselect Tabs icons You can add a tab with an icon if somehow that tab is special tsuiTopBartabspush label Icon Tab icon tsicontodo tsuiTopBartabspush label Icon Tab icon tsicontodo Tab counters You can add a counter to the tabs for whatever reason you like tsuiTopBartabsforEachfunctiontab tabcounter MathceilMathrandom 10 tsuiTopBartabsforEachfunctiontab tabcounter MathceilMathrandom 10 When the counter reaches zero it disappears tsuiTopBartabsforEachfunctiontab tabcounter tsuiTopBartabsforEachfunctiontab tabcounter Closeable tabs You can create closeable tabs but note that the tab must be selected before it can be closed You can return false in the onclose method to prevent the tab from closing if this would otherwise cause data loss tsuiTopBartabspush label Closeable Tab closeable true selected true onclose function tsuiNotificationsuccessthislabel closed tsuiTopBartabspush label Closeable Tab closeable true selected true onclose function tsuiNotificationsuccessthislabel closed NewTab button You can allow the user to create new tabs via a special button as seen in popular browsers Note that the button just triggers a callback and that the new tab must be created manually In the example below the selected property also selects the tab var tabs tsuiTopBartabs tabsshowNewfunction onclick tabspush label My New Tab selected true var tabs tsuiTopBartabs tabsshowNewfunction onclick tabspush label My New Tab selected true If you regret this later on you can also hide the button tsuiTopBartabshideNew tsuiTopBartabshideNew Heres a summary of the tabs collection and tab model TopBarbuttons Add buttons to the TopBar with the buttons method This both sets and gets If you omit the argument youll get the current buttons jQuery style tsuiTopBarbuttons label Primary type tsprimary label Secondary type tssecondary label Tertiary One label Tertiary Two tsuiTopBarbuttons label Primary type tsprimary label Secondary type tssecondary label Tertiary One label Tertiary Two You can use array methods like push pop shift unshift splice reverse and so on to manage buttons Just note that the buttons length is readonly The buttons type property works like the CSS class for a regular Button The TopBar will automatically sort all buttons from primary to tertiary If theres more than one tertiary button these will be pushed to an Aside In the mobile breakpoint all the buttons will be pushed to an Aside Buttons wont actually do anything unless you define the onclick method tsuiTopBarbuttonssplice0 1 label Click me type tsprimary onclick function thislabel Thanks tsuiTopBarbuttonssplice0 1 label Click me type tsprimary onclick function thislabel Thanks Fortunately you can always change what happens when a button gets clicked tsuiTopBarbuttonsforEachfunctionbutton index buttonlabel Button index 1 buttononclick function tsuiNotificationsuccessthislabel tsuiTopBarbuttonsforEachfunctionbutton index buttonlabel Button index 1 buttononclick function tsuiNotificationsuccessthislabel Query buttons You can locate buttons by index in the buttons collection But since this isnt likely to match the order in which they appear on screen its easier to give the buttons an id and find them using buttonsget var buttons tsuiTopBarbuttons buttonspush id examplebutton var button buttonsgetexamplebutton buttonlabel My Button buttontype tssecondary var buttons tsuiTopBarbuttons buttonspush id examplebutton var button buttonsgetexamplebutton buttonlabel My Button buttontype tssecondary Hide buttons You can hide and show buttons You can also toggle visible tsuiTopBarbuttonsforEachfunctionbutton ifbuttonvisible buttonhide else buttonshow tsuiTopBarbuttonsforEachfunctionbutton ifbuttonvisible buttonhide else buttonshow Disable buttons You can disable and enable buttons You can also toggle disabled tsuiTopBarbuttonsforEachfunctionbutton ifbuttondisabled buttonenable else buttondisable tsuiTopBarbuttonsforEachfunctionbutton ifbuttondisabled buttonenable else buttondisable Busy buttons We can display a temporary progress indicator with the busy and done methods var button tsuiTopBarbuttons0 buttonbusy setTimeoutfunction buttondone 1000 var button tsuiTopBarbuttons0 buttonbusy setTimeoutfunction buttondone 1000 The busy method supports an optional status message var button tsuiTopBarbuttons0 buttonbusyMaking progress setTimeoutfunction buttondone 1000 var button tsuiTopBarbuttons0 buttonbusyMaking progress setTimeoutfunction buttondone 1000 Button groups You can also group buttons in arrays to create button groups that look like this tsuiTopBarbuttons label Normal label Normal label Accept type tsprimary label Reject type tsdanger tsuiTopBarbuttons label Normal label Normal label Accept type tsprimary label Reject type tsdanger You can of course also create grouped buttons with icons instead of text var group tsuiTopBarbuttons2 grouppush icon tsiconother type tssecondary var group tsuiTopBarbuttons2 grouppush icon tsiconother type tssecondary Heres a summary of the buttons collection and button model TopBar Back Forward The TopBar features both Back and Forward buttons for use in drill down scenarios tsuiTopBarshowBackfunction consolelogBack showNextfunction consolelogNext tsuiTopBarshowBackfunction consolelogBack showNextfunction consolelogNext You can also hide the Back and Forward buttons Since the buttons obscure the tabs you might actually like to do that now tsuiTopBarhideBackhideNext tsuiTopBarhideBackhideNext Note that tabbed navigation is not supposed to coexist with Back and Forward buttons Hide show the TopBar You can hide the TopBar but not in mobile breakpoint see below Note that this operation will clear the contents of the TopBar tsuiTopBarhide tsuiTopBarhide You can also show it again Because the content was cleared well also restore it tsuiTopBarshow restoreTopBar tsuiTopBarshow restoreTopBar When you resize the window to mobile breakpoint the hidden TopBar will be shown again automatically Thats because the TopBar is used to access the main navigation Without the TopBar you would be stuck in the app forever But since you chose to hide the TopBar we can assume that the content of the TopBar is not relevant Therefore Since we dont want to show an outdated TopBar to mobile users the content of the TopBar will be cleared when you hide it To restore the old content you will simply have to populate the TopBar again If you dont want your app to feature a TopBar under any circumstance you can simply remove the whole from the HTML TopBar summary Heres a summary of the TopBar methods including some bonus not yet discussed If you find a bug or need a feature Create GitHub Issue"},{"title":"Buttons","href":"components/buttons/buttons.html","content":"Buttons Group buttons in menus to unlock advanced layout options Assign datatsButtons attribute to a menu to initialize it as a Buttons menu Button One Button Two Button One Button Two When in menus buttons stack vertically and stretch to fill the width You can omit the tsbutton attribute on buttons it is implied You can also omit the tstertiary classname on the buttons it is assumed by default Button layouts The menu can be assigned a classname to layout the buttons horizontally Accept Reject Accept Reject The classname tstt indicates that two buttons should both display text instead of icons If you add both the layout will take care of hiding one or the other A special classname tsjoin has been added to join the buttons together We support the following permutations edbmldeclareedbmlklDUi2asfunction edbml use strict var out edbmlout txt edbmlsafetext val edbmlsafeattr tstt tsit tsti tsiit tsiti tstii mapfunctionc rendermenuc return c forEachfunctionc rendermenuc tsjoin function rendermenuc1 c2 var cname c1 c2 outhtml c1substringtslengthsplitforEachfunction outhtml txtcname outhtml return outwrite The classname shown on buttons should in all cases go on the menu element and not on the button elements If you find a bug or need a feature Create GitHub Issue"},null,{"title":"Button Gallery","href":"components/buttons/gallery.html","content":"Button Gallery function togglekey checkbox var menu documentquerySelector key var buttons menuquerySelectorAllbutton guiArrayfrombuttonsforEachfunctionb bdisabled bdisabled tsdoxtabs edbmldeclareedbmlZsJn2z1asfunction edbml use strict var out edbmlout att edbmlatt txt edbmlsafetext val edbmlsafeattr layout edbmlinputtsuiLayoutModel var spirit this var backgroundcolors tsbglite tsbgwhite tsbgyellow tsbgdark tsbgblue tsbgred tsbgorange tsbggreen tsbgpurple var buttonlabeltexts Primary Secondary Tertiary var buttonclassnames tsprimary tssecondary tstertiary rendercolumnslayoutbreakpoint desktop function rendercolumnsdesktop if desktop outhtml backgroundcolorsforEachfunctionclassname outhtml txtclassname outhtml backgroundcolorsforEachfunctionclassname outhtml renderbuttons outhtml outhtml else backgroundcolorsforEachfunctionclassname outhtml renderbuttons outhtml function renderbuttons var key guiKeyMastergenerateKey outhtml buttonclassnamesforEachfunctionclassname i outhtml attdisabled spiritdisabled disabled null outhtml txtbuttonlabeltextsi outhtml renderTogglekey function rendernested outhtml Nested tsbgwhite buttonclassnamesforEachfunctionclassname i outhtml outhtml function renderTogglekey outhtml Disabled return outwrite withInstructions input name layout type tsuiLayoutModel "},null,{"title":"Button","href":"components/buttons/index.html","content":"Button Use button classnames to prioritize the possible actions in your app Assign datatsButton to a button to initialize it as a Button Default Button Default Button The default button looks like a link but some CSS classnames can be added to make it look more like a button Primary Secondary Tertiary Primary Secondary Tertiary Button icons Icons go into a separate i element You can see a list of all icons Button Text Button Text Youll notice in the code snippet that the span has been set to displaynone Buttons should never show both text and icon at the same time If you need both its up to you to hide one or the other In this example the button has been rigged up to show the icon only in the mobile breakpoint Hidden In Mobile Hidden In Mobile Button spinner Assign the datatsbusy attribute to a button to initialize a spinner Primary show spinner Micro Button You can add class tsmicro to get a micro button Primary Secondary Tertiary Primary Secondary Tertiary You can group buttons in menus to unlock advanced layout options If you find a bug or need a feature Create GitHub Issue"},{"title":"","href":"components/buttons/tabs.html","content":""},null,null,null,null,null,{"title":"CompanyCard","href":"components/cards/companycard.html","content":"CompanyCard tsdoxtabs CompanyCard In this first iteration the CompanyCard is simply a HTML rendering that you can feed with JSON in various ways You can initialize a CompanyCard with the attribute datatsCompanyCard Even without any data the card takes on a cardlike appearance If you are using Angular or jQuery you might like to feed the card through a JavaScript API as we will see you can however also embed the data directly in the markup Embedded JSON Serverside devs and UX designers might like to embed the JSON in the HTML Because this is JSON you should use double quotes and omit trailing commas id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Tradeshift logo assetslogopng size 100249 location San Francisco California industry Software IT connection 2 id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Tradeshift logo assetslogopng size 100249 location San Francisco California industry Software IT connection 2 Encoded JSON You can also embed the JSON in an attribute datatsrender The JSON string must be encoded in the format returned by method encodeURIComponentjson Remember to trim the JSON string before you encode it Render programatically You can grab a hold of the card and instruct it to render some JSON data tsuigetmycard card cardrender id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Tradeshift logo assetslogopng size 100249 location San Francisco California industry Software IT connection 2 tsuigetmycard card cardrender id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Tradeshift logo assetslogopng size 100249 location San Francisco California industry Software IT connection 2 We notice that the connection status is indicated by a number The number matches an index in the following array which declares the label and icon tsuiCompanyCardconnectionTypes Your company tsiconnetwork Request sent tsiconnetwork Connected tsiconnetwork Registration in progress tsiconnetwork In your Google Contacts tsiconnetwork Via email only tsiconnetwork This array is crowdsourced You can modify the array in your app simply by copypasting the code above into your initialization script You can also use numbers instead of strings to indicate size and industry cardrender id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Tradeshift size 3 industry 6 If you provide a number instead of a string well look it up in these lists tsuiCompanyCardcompanySizes 1 110 1100 100249 250500 5001000 tsuiCompanyCardindustryTypes Airline Corporation Educational Organization Government Organization Local Business NGO Software IT Performing Group Sports Team You are also welcome to overwrite these arrays in your app Thats it for now"},{"title":"CompanyCard extras","href":"components/cards/extras.html","content":"CompanyCard extras These are considered experimental features You can feed data to your cards without poking around in the DOM In your HTML you must declare your cards with a datatsid attribute assigned You can now or even before import the JSON from a demo file and instruct the cards to render getJSONassetscardsjson functionjson tsuiCompanyCardrenderjson The details view The card should eventually be able to render its own details view so that it looks the same outside of V4 Theres a lot of infrastructure that needs to happen first not least with translations in the Runtime but it could look like this tsuigetmycardopen tsuigetmycardopen If you find a bug or need a feature Create GitHub Issue"},{"title":"","href":"components/cards/tabs.html","content":""},{"title":"UserCard","href":"components/cards/usercard.html","content":"UserCard figure output textalign center tsdoxtabs UserCard In this first iteration the UserCard can simply show some user details in an Aside The properties are all optional but you should at least include the name tsuiUserCard id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Wired Earp image assetswiredearppng title EDB Programmer role Gentleman Spy email jmotradeshiftcom company Tradeshift companyUrl httptradeshiftcom open tsuiUserCard id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Wired Earp image assetswiredearppng title EDB Programmer role Gentleman Spy email jmotradeshiftcom company Tradeshift companyUrl httptradeshiftcom open"},{"title":"DatePicker","href":"components/datepicker/index.html","content":"DatePicker Calendar widget that appears in Aside Used in Forms for an implementation of elements The DatePicker can be launched with a JavaScript API You should implement the onselect method to get notified whenever the user picks a date Note that you must manually open and close the DatePicker var datePicker tsuiDatePicker title Your Birthday value 19730326 onselect functionnewval oldval tsuiNotificationsuccessthisvalue thisclose onclosed function thisdispose datePickeropen var datePicker tsuiDatePicker title Your Birthday value 19730326 onselect functionnewval oldval tsuiNotificationsuccessthisvalue thisclose onclosed function thisdispose datePickeropen You can specify a min and max value tsuiDatePicker title Your Birthday value 19840523 min 19840101 max 19851224 onselect function thisclose onclosed function thisdispose open tsuiDatePicker title Your Birthday value 19840523 min 19840101 max 19851224 onselect function thisclose onclosed function thisdispose open The object argument configures a tsuiDatePickerModel as outlined below tsuiDatePickerModel Instance properties title string Appears as the title of the DatePicker value string The selected date Must be dashseparated ISO 8601 formatted date string eg 20150101 Instance methods open void Open the DatePicker close void Close the DatePicker onselect void Called whenever selection changes with two arguments newval and oldval onclosed void Event listener for close event Called after aside closing animation is completed dispose void Cleanup the DataPicker recommended If you find a bug or need a feature Create GitHub Issue"},{"title":"Dialog","href":"components/dialogs/index.html","content":"Dialog The Dialog API can be used to ask simple questions much like the JavaScript confirm method You can launch a Dialog with methods to handle OK and Cancel tsuiDialogconfirmWill you try onaccept function tsuiNotificationsuccessGood luck oncancel function tsuiNotificationsuccessCome back later tsuiDialogconfirmWill you try onaccept function tsuiNotificationsuccessGood luck oncancel function tsuiNotificationsuccessCome back later You are encouraged to specify the text of the OK button The button should attempt to indicate what happens when you press it tsuiDialogconfirmShow the Notification Show It onaccept function tsuiNotificationsuccessGood choice tsuiDialogconfirmShow the Notification Show It onaccept function tsuiNotificationsuccessGood choice You can add a third string argument to specify the Cancel text Buttons setup Dialog buttons are secondary blue by default but you can choose to make the accept or cancel button primary You can also tweak the default focus tsuiDialogconfirmSign up for Tradeshift Join Now primary accept focused accept tsuiDialogconfirmSign up for Tradeshift Join Now primary accept focused accept You can change the label of both the primary and secondary buttons tsuiDialogconfirmSign up for Tradeshift Join Now Not Now primary accept focused accept tsuiDialogconfirmSign up for Tradeshift Join Now Not Now primary accept focused accept Warning dialogs You can launch special dialogs to confirm choices of more dire consequence tsuiDialogwarningThis will delete the thing Delete It onaccept function tsuiDialogdanger Are you absolutely sure you want to permanently delete the whole thing Delete It tsuiDialogwarningThis will delete the thing Delete It onaccept function tsuiDialogdanger Are you absolutely sure you want to permanently delete the whole thing Delete It Dialog icons You can point the icon property to an alternative icon class but you should stick to the stock icons whenever possible so that the user can easily recognize the dialog type tsuiDialogconfirmProceed to Checkout Check Out icon tsiconcart primary accept focused accept tsuiDialogconfirmProceed to Checkout Check Out icon tsiconcart primary accept focused accept If you find a bug or need a feature Create GitHub Issue"},{"title":"Footer Actions","href":"components/footer/actions.html","content":"Footer actions Footer actions can be used to manipulate selected objects of any kind They appear in a separate toolbar so that they never conflict with the normal buttons This toolbar can also be configured with a status message and this checkbox The actions method both sets and gets the actions If you omit the argument youll get the current actions jQuery style In real life the actions should only appear whenever the user has selected something with the mouse or keyboard so we will just have to pretend that something is selected tsuiFooteractions label Move Up icon tsicontriangleup label Move Down icon tsicontriangledown label Move Left icon tsicontriangleleft label Move Right icon tsicontriangleright label Dont Move icon tsiconhalt onclick tsuiFooteractionsclear tsuiFooteractions label Move Up icon tsicontriangleup label Move Down icon tsicontriangledown label Move Left icon tsicontriangleleft label Move Right icon tsicontriangleright label Dont Move icon tsiconhalt onclick tsuiFooteractionsclear You can use array methods like push pop shift unshift splice and so on to manage actions just note that the actions length is a readonly property To ensure consistency actions should always have both an icon and a label much unlike the buttons Hide actions You can hide and show actions You can also toggle visible tsuiFooteractionsforEachfunctionaction ifactionvisible actionhide else actionshow tsuiFooteractionsforEachfunctionaction ifactionvisible actionhide else actionshow Disable actions You can disable and enable action You can also toggle disabled tsuiFooteractionsforEachfunctionaction ifactiondisabled actionenable else actiondisable tsuiFooteractionsforEachfunctionaction ifactiondisabled actionenable else actiondisable Busy actions We can display a temporary progress indicator with the busy and done methods var action tsuiFooteractions0 actionbusy setTimeoutfunction actiondone 1000 var action tsuiFooteractions0 actionbusy setTimeoutfunction actiondone 1000 The busy method supports an optional message var action tsuiFooteractions0 actionbusyMaking progress setTimeoutfunction actiondone 1000 var action tsuiFooteractions0 actionbusyMaking progress setTimeoutfunction actiondone 1000 Heres a summary of the actions collection and action model Status message We can configure the actionbar with a status message When a selection is made the massage could be something like 23 products selected When nothing is selected it could perhaps be something like Showing 1020 out of 123 products tsuiFooterstatus23 of one million products selected tsuiFooterstatus23 of one million products selected If you call linkable you can also some links in the message Beware of phishing tsuiStatusBarlinkablemessage Please visit Tradeshifthttpwwwtradeshiftcom tsuiStatusBarlinkablemessage Please visit Tradeshifthttpwwwtradeshiftcom You can pass a callback function to be invoked whenever a link is clicked tsuiStatusBarlinkablefunction onclickurl tsuiNotificationsuccessurl thisstatusThanks messagePlease click the linkThe URL can be any string tsuiStatusBarlinkablefunction onclickurl tsuiNotificationsuccessurl thisstatusThanks messagePlease click the linkThe URL can be any string Checkbox Theres also a checkbox which conceptually can be used to manage selections This is the minimum viable implementation tsuiFootercheckbox onclick function thischecked thischecked tsuiFootercheckbox onclick function thischecked thischecked You must manually toggle the checked property This will give you a chance to let the user confirm if he really intends to select millions of products or if he really wants to clear a selection that took him hours to complete Here is the CheckBoxModel Use the indeterminate property if state that is neither checked nor unchecked Its a inbetween state that can be used show a partial selection and to check all selections var i 0 tsuiFootercheckbox onclick function switch i 3 case 0 unchecked thischecked false tsuiFooterstatus0 of 3 items selected break case 1 indeterminate overrides checked thischecked true thisindeterminate true tsuiFooterstatus1 of 3 items selected break case 2 checked thisindeterminate false tsuiFooterstatus3 of 3 items selected break status0 of 3 items selected var i 0 tsuiFootercheckbox onclick function switch i 3 case 0 unchecked thischecked false tsuiFooterstatus0 of 3 items selected break case 1 indeterminate overrides checked thischecked true thisindeterminate true tsuiFooterstatus1 of 3 items selected break case 2 checked thisindeterminate false tsuiFooterstatus3 of 3 items selected break status0 of 3 items selected The example above shows that the indeterminate property will take precedence over the checked property If you find a bug or need a feature Create GitHub Issue"},{"title":"Footer Buttons","href":"components/footer/buttons.html","content":"Footer buttons Add buttons to the Footer with the buttons method This both sets and gets If you omit the argument youll get the current buttons jQuery style tsuiFooterbuttons label Primary type tsprimary label Secondary type tssecondary label Tertiary One label Tertiary Two tsuiFooterbuttons label Primary type tsprimary label Secondary type tssecondary label Tertiary One label Tertiary Two You can use array methods like push pop shift unshift splice reverse and so on to manage buttons Just note that the buttons length is readonly The buttons type property works like the CSS class for a regular Button The Footer will automatically sort all buttons from primary to tertiary If theres more than one tertiary button these will be pushed to an Aside In the mobile breakpoint all the buttons will be pushed to an Aside Buttons wont actually do anything unless you define the onclick method tsuiFooterbuttonssplice0 1 label Click me type tsprimary onclick function thislabel Thanks tsuiFooterbuttonssplice0 1 label Click me type tsprimary onclick function thislabel Thanks Fortunately you can always change what happens when a button gets clicked tsuiFooterbuttonsforEachfunctionbutton index buttonlabel Button index 1 buttononclick function tsuiNotificationsuccessthislabel tsuiFooterbuttonsforEachfunctionbutton index buttonlabel Button index 1 buttononclick function tsuiNotificationsuccessthislabel Query buttons You can locate buttons by index in the buttons collection But since this isnt likely to match the order in which they appear on screen its easier to give the buttons an id and find them using buttonsget var buttons tsuiFooterbuttons buttonspush id examplebutton var button buttonsgetexamplebutton buttonlabel My Button buttontype tssecondary var buttons tsuiFooterbuttons buttonspush id examplebutton var button buttonsgetexamplebutton buttonlabel My Button buttontype tssecondary Hide buttons You can hide and show buttons You can also toggle visible tsuiFooterbuttonsforEachfunctionbutton ifbuttonvisible buttonhide else buttonshow tsuiFooterbuttonsforEachfunctionbutton ifbuttonvisible buttonhide else buttonshow Disable buttons You can disable and enable buttons You can also toggle disabled tsuiFooterbuttonsforEachfunctionbutton ifbuttondisabled buttonenable else buttondisable tsuiFooterbuttonsforEachfunctionbutton ifbuttondisabled buttonenable else buttondisable Busy buttons We can display a temporary progress indicator with the busy and done methods var button tsuiFooterbuttons0 buttonbusy setTimeoutfunction buttondone 1000 var button tsuiFooterbuttons0 buttonbusy setTimeoutfunction buttondone 1000 The busy method supports an optional status message var button tsuiFooterbuttons0 buttonbusyMaking progress setTimeoutfunction buttondone 1000 var button tsuiFooterbuttons0 buttonbusyMaking progress setTimeoutfunction buttondone 1000 Button groups You can also group buttons in arrays to create button groups that look like this tsuiFooterbuttons label Normal label Normal label Accept type tsprimary label Reject type tsdanger tsuiFooterbuttons label Normal label Normal label Accept type tsprimary label Reject type tsdanger You can of course also create grouped buttons with icons instead of text var group tsuiFooterbuttons2 grouppush icon tsiconother type tssecondary var group tsuiFooterbuttons2 grouppush icon tsiconother type tssecondary Heres a summary of the buttons collection and button model If you find a bug or need a feature Create GitHub Issue"},{"title":"Footer Collaboration","href":"components/footer/collabbutton.html","content":"Footer collabbutton The Footer features a special button which is dedicated to launching the collaboration panel To show the button simply call the method configbutton with a callback tsuiFootercollabbuttonfunction onclick tsuiNotificationsuccessGo collaborate tsuiFootercollabbuttonfunction onclick tsuiNotificationsuccessGo collaborate Note that the Footer doesnt automatically initialize or resume the collbaroration The API for this will be provided elsewhere You can hide the collaboration button by passing null to the same method tsuiFootercollabbuttonnull tsuiFootercollabbuttonnull If you find a bug or need a feature Create GitHub Issue"},{"title":"Footer Configuration","href":"components/footer/configbutton.html","content":"Footer configbutton There Footer can be fitted with a special button for the purpose of configuring things To show the button simply call the method configbutton with a callback tsuiFooterconfigbuttonfunction onclick tsuiNotificationsuccessGo configure tsuiFooterconfigbuttonfunction onclick tsuiNotificationsuccessGo configure What happens when you click the button is completely up to you Fortunately you can also hide the button again by passing null to the same method tsuiFooterconfigbuttonnull tsuiFooterconfigbuttonnull If you find a bug or need a feature Create GitHub Issue"},{"title":"Footer Gallery","href":"components/footer/gallery.html","content":"Footer gallery Here you can test how the Footer behaves when you enable all the features 1 Add a pager tsuiFooterpager pages 23 page 0 onselect functionindex consolelogindex tsuiFooterpager pages 23 page 0 onselect functionindex consolelogindex 2 Add some buttons tsuiFooterbuttons label Button 1 type tsprimary label Button 2 type tssecondary label Button 3 label Button 4 label Button 5 tsuiFooterbuttons label Button 1 type tsprimary label Button 2 type tssecondary label Button 3 label Button 4 label Button 5 3 Add more buttons until they crash into the Pager Behold the second toolbar tsuiFooterbuttonssplice2 0 label Bonus Button type tssecondary tsuiFooterbuttonssplice2 0 label Bonus Button type tssecondary 4 The actions will appear in yet another toolbar Thats right tsuiFooteractions label Move Up icon tsicontriangleup label Move Down icon tsicontriangledown label Move Left icon tsicontriangleleft label Move Right icon tsicontriangleright label Dont Move icon tsiconhalt statusSomething is selectedcheckbox onclick function thischecked thischecked tsuiFooteractions label Move Up icon tsicontriangleup label Move Down icon tsicontriangledown label Move Left icon tsicontriangleleft label Move Right icon tsicontriangleright label Dont Move icon tsiconhalt statusSomething is selectedcheckbox onclick function thischecked thischecked 5 Finally add the configuration and collaboration buttons tsuiFooterconfigbuttonfunction onclick tsuiNotificationsuccessGo configure collabbuttonfunction onclick tsuiNotificationsuccessGo collaborate tsuiFooterconfigbuttonfunction onclick tsuiNotificationsuccessGo configure collabbuttonfunction onclick tsuiNotificationsuccessGo collaborate With the Footer fully equipped we can try to hide and destroy these things again Hide something or everything If you need to temporarily hide a single Footer member you can call the associated method without any arguments to get a hold of the thing and then call the hide and show methods You can also toggle the visible property var thing pause action setTimeoutaction 500 function togglethings ifthingslength ifthing thingsshift thinghide pause thingshow pause togglethings else togglethings tsuiFooterbuttons tsuiFooteractions tsuiFooterpager tsuiFootercheckbox tsuiFootercollabbutton tsuiFooterconfigbutton var thing pause action setTimeoutaction 500 function togglethings ifthingslength ifthing thingsshift thinghide pause thingshow pause togglethings else togglethings tsuiFooterbuttons tsuiFooteractions tsuiFooterpager tsuiFootercheckbox tsuiFootercollabbutton tsuiFooterconfigbutton Remember that the hidden thing remains hidden until you show it again You can of course also show and hide the whole Footer Again note that it will remain hidden tsuiFooterhide setTimeout tsuiFootershow 500 tsuiFooterhide setTimeout tsuiFootershow 500 Clear something or everything If you are sure that you wont need to show a configured Footer member again at some point in the future it is advised that you completely destroy it instead of just hide it You can do this by passing null to the associated method function destructiveactions actionsshift ifactionslength setTimeout destructiveactions 500 tsuiFooterpagernull tsuiFooterstatusnull tsuiFootercheckboxnull tsuiFooterbuttonsnull tsuiFooteractionsnull tsuiFootercollabbuttonnull tsuiFooterconfigbuttonnull function destructiveactions actionsshift ifactionslength setTimeout destructiveactions 500 tsuiFooterpagernull tsuiFooterstatusnull tsuiFootercheckboxnull tsuiFooterbuttonsnull tsuiFooteractionsnull tsuiFootercollabbuttonnull tsuiFooterconfigbuttonnull You can of course also just clear everything and the Footer will automatically hide tsuiFooterclear tsuiFooterclear If you find a bug or need a feature Create GitHub Issue"},{"title":"Footer Pager","href":"components/footer/index.html","content":"Footer This is a developer preview All features can be expected to change The Footer appears near the bottom of the page where it is commonly used to display some buttons All features are controlled with an API that looks something like this tsuiFooterbuttons label Continue type tsprimary onclick function toplocationhash componentsfooterbuttonshtml tsuiFooterbuttons label Continue type tsprimary onclick function toplocationhash componentsfooterbuttonshtml Heres a quick overview of the Footer API You can read more in the following pages If you find a bug or need a feature Create GitHub Issue"},{"title":"Footer Pager","href":"components/footer/pager.html","content":"Footer pager The Footer features a Pager The pager method both sets and gets the Pager If you omit the argument youll get the current Pager jQuery style You can pass null to the method to destroy the Pager once you are done with it tsuiFooterpager pages 23 page 0 onselect functionindex consolelogindex tsuiFooterpager pages 23 page 0 onselect functionindex consolelogindex If you need to update the index later on for example to support history navigation it is recommended that you change the page property of the existing Pager instead of initializing a whole new Pager You can just call the same method without arguments tsuiFooterpagerpage 23 If you find a bug or need a feature Create GitHub Issue"},{"title":"","href":"components/footer/tabs.html","content":""},null,{"title":"Form Autocomplete","href":"components/forms/autocomplete.html","content":"Form Autocomplete tsdoxtabs Autocomplete You can have an input field suggest results to the user and can be navigated using the keyboard or the mouse Basic Usage Loading the autocomplete data from a static array tsuigetmystaticautocomplete autocomplete autocompletedata key 0 value zero key 1 value one key 2 value two key 3 value three key 4 value four key 5 value five key 6 value six key 7 value seven key 8 value eight key 9 value nine tsuigetmystaticautocomplete autocomplete autocompletedata key 0 value zero key 1 value one key 2 value two key 3 value three key 4 value four key 5 value five key 6 value six key 7 value seven key 8 value eight key 9 value nine Autocomplete from array External Data Loading all results from an external JSON endpoint but using the built in filtering tsuigetmyadvancedautocomplete autocomplete getJSONassetsautocompletejson functionjson autocompletedatajson tsuigetmyadvancedautocomplete autocomplete getJSONassetsautocompletejson functionjson autocompletedatajson Autocomplete from JSON Advanced Usage Its possible to override the filtering functionality to supply the user with any data youd like tsuigetmyfancyautocomplete autocomplete autocompleteonfilterfunctionfilter var output for var i parseIntMathrandom 10 1 10 i 0 i outputpush key i value MathrandomtoString36substr2 5 return output tsuigetmyfancyautocomplete autocomplete autocompleteonfilterfunctionfilter var output for var i parseIntMathrandom 10 1 10 i 0 i outputpush key i value MathrandomtoString36substr2 5 return output Autocomplete with custom results Overriding onselect onselect can be overridden to run your own code when an element is selected either with the keyboard or the mouse tsuigetmyspecialautocomplete autocomplete autocompletedata key 0 value zero key 1 value one autocompleteonselectfunctionitem tsuiNotificationsuccess itemvalue selected return itemvalue tsuigetmyspecialautocomplete autocomplete autocompletedata key 0 value zero key 1 value one autocompleteonselectfunctionitem tsuiNotificationsuccess itemvalue selected return itemvalue Autocomplete with special onselect"},{"title":"Custom Select","href":"components/forms/custom-select.html","content":"Custom Select documentreadyfunction usercontainer divclickfunctione var name ecurrentTargetattrname tsuigetmyAside aside asideclose mySelectvalname tsuiNotificationsuccessname usercontainer div margin 11px cursor pointer tsdoxtabs Custom Select You can handle the onclick action on a select input element to make your own select if you set the attribute datatscustomtrue Following example is custom user select which made step by step 1 Create your own select input element Select Karl Benson Marshall Garrett Natalie Carr Rochelle Cox Mae Schultz Jimmie Edwards Select Karl Benson Marshall Garrett Natalie Carr Rochelle Cox Mae Schultz Jimmie Edwards 2 Create your own Aside and fill up options in the panel of the Aside Karl Benson Marshall Garrett Natalie Carr Rochelle Cox Mae Schultz Jimmie Edwards Karl Benson Marshall Garrett Natalie Carr Rochelle Cox Mae Schultz Jimmie Edwards 3 Handle the onClick event of the options documentreadyfunction usercontainer divclickfunctione var name ecurrentTargetattrname tsuigetmyAside aside asideclose mySelectvalname tsuiNotificationsuccessname documentreadyfunction usercontainer divclickfunctione var name ecurrentTargetattrname tsuigetmyAside aside asideclose mySelectvalname tsuiNotificationsuccessname 4 You can run the following code first mySelectclickfunction tsuigetmyAside aside asideopen mySelectclickfunction tsuigetmyAside aside asideopen 5 Click the select below to check how it works Good luck Select Karl Benson Marshall Garrett Natalie Carr Rochelle Cox Mae Schultz Jimmie Edwards Karl Benson Marshall Garrett Natalie Carr Rochelle Cox Mae Schultz Jimmie Edwards"},{"title":"Disabled & Readonly Fields","href":"components/forms/disabled.html","content":"Disabled and readonly fields Form fields can be set to be disabled or readonly the same way you would in XHTML5 You can set datatspreview attribute to preview whole form input typetext disabled Disabled Text Disabled Text input typetext readonly Readonly Text Readonly Text textarea disabled Disabled Textarea Fatback kevin picanha pork loin kielbasa turducken doner Beef ribs tongue ham ball tip hamburger pork loin biltong sausage salami sirloin tenderloin kevin shank pig meatloaf Disabled Textarea Fatback kevin picanha pork loin kielbasa turducken doner Beef ribs tongue ham ball tip hamburger pork loin biltong sausage salami sirloin tenderloin kevin shank pig meatloaf date disabled Disabled Date Disabled Date select disabled Disabled Select One Two Three Four Five Disabled Select One Two Three Four Five input typeradio disabled There is no choice Red pill Blue pill There is no choice Red pill Blue pill input typecheckbox disabled By browsing this page you agree to our terms I agree to something I agree to something by default By browsing this page you agree to our terms I agree to something I agree to something by default input typecheckbox disabled alternate version Its not a bug its a feature Secret Feature Secret Feature On by default Its not a bug its a feature Secret Feature Secret Feature On by default form datatspreviewtrue If you find a bug or need a feature Create GitHub Issue"},{"title":"Form Example","href":"components/forms/example.html","content":"Form Example function Controllerscope scopemodel poref invalid gln 1234567890123 windowangularmoduleapp controllerController scope Controller tsdoxtabs ErrorInfo example Here you can see a full example on how to use the error and info helpers for form fields using AngularJS Text PO line item reference Error PO line item reference Must be 4 numeric digits in length Must be present on the related PO document GLN Optional Definition GLN A GLN Global Location Number is a globally unique 13 digit numeric identifier that is used to access data about a location More information about the GLN System Error GLN Must be 13 numeric digits in length Can only contain numbers Heres the source for the form above Text PO line item reference Error PO line item reference Must be 4 numeric digits in length Must be present on the related PO document GLN Optional Definition GLN A GLN Global Location Number is a globally unique 13 digit numeric identifier that is used to access data about a location More information about the GLN System Error GLN Must be 13 numeric digits in length Can only contain numbers If you find a bug or need a feature Create GitHub Issue"},{"title":"Form","href":"components/forms/index.html","content":"Form Provides styling and behavior for form controls and error messages Assign datatsForm to a form to initialize as a Form Form components depend on specific internal element structure in order to initialize and style their contents Most components adhere to this structure textarea Starts out with three lines but will expand up to ten as content is entered The rows attribute can be used to adjust the initial amount of lines to show Textarea Textarea Textarea You can specify typesubmit to make the texarea submit the form on ENTER In this mode newlines may still be entered while pressing the SHIFT key Press SHIFT to ENTER newlines Press SHIFT to ENTER newlines Press SHIFT to ENTER newlines input typetext Text Text Text input typetel Tel Tel Tel input typeemail Email Email Email input typenumber Set the class classtsright on the label to make your number text align right Number Number Number input typedate Date Date Date select The select will open in an Aside but youll mantain it like a normal select Note that the select only triggers a change event when the Aside is fully closed Set the attribute datatscustomtrue to handle your own select event Select One Two Three Select One Two Three Select One Two Three You can configure the select with a default placeholder in a twostep process Add the placeholder attribute to the select Leave the first option empty no option text Select with placeholder 5 23 Select with placeholder 5 23 Select with placeholder 5 23 When a selection is made the user can revert to the default no selection by clicking the selected option a second time If you dont want to allow this you should make sure to remove the empty option This strange pattern ensures maximum compatibility with Angular 1x where an empty option is automatically inserted until a selection is performed To also allow unselection in Angular you must manually create the empty option and make sure that it is explicitly selected as default select multiple The select multiple only triggers a change when the Done button is pressed You can customize the button label by adding a button to the label element but note that this only configures the text on the button eg no event listeners are fired Select multiple One Two Three Four Five Cool apply changes Select multiple One Two Three Four Five Cool apply changes Select multiple One Two Three Four Five Cool apply changes input typeradio Radio element Generally used to choose something Choose wisely Red pill Blue pill Choose wisely Red pill Blue pill Choose wisely Red pill Blue pill input typecheckbox Checkbox element Generally used to indicate consent on forms Legally Binding Contract I agree to something I agree to something by default Legally Binding Contract I agree to something I agree to something by default Legally Binding Contract I agree to something I agree to something by default input typetextbox alternate version We call it the switch Used mainly for toggling preferencessettings Note that switch differs from the checkbox only by the order of HTML elements Settings Page Secret Feature Secret Feature On by default Settings Page Secret Feature Secret Feature On by default Settings Page Secret Feature Secret Feature On by default Errors and info To mark a control as invalid simply add the class tserror to the label Text Text Text To display an error message one must mark the control as errored using the tserror class as well as add the error message markup to the page Text Text An explanation of the error in question Another explanation of the error in question Text Text An explanation of the error in question Another explanation of the error in question To display an info section use the tsinfo class Text Text An information about the field Another information about the field Text Text An information about the field Another information about the field If you find a bug or need a feature Create GitHub Issue"},{"title":"Form Example","href":"components/forms/redesign.html","content":"Standard Text Text with custom icon Text with no icon Textarea Textarea Select One Two Three Select with placeholder One Two Three Select multiple One Two Three Four Five Cool apply changes Date Radios Option One Option Two Checkbox I agree I dont agree Switch I agree I dont agree Disabled Text Text with custom icon Text with no icon Textarea Textarea Select One Two Three Select with placeholder One Two Three Select multiple One Two Three Four Five Cool apply changes Date Radios Option One Option Two Checkbox I agree I dont agree Switch I agree I dont agree TODO Ghost optiongroup label only when all options are disabled Readonly Text Text with custom icon Text with no icon Textarea Textarea Select One Two Three Select with placeholder One Two Three Select multiple One Two Three Four Five Cool apply changes Date Note that readonly has no function on radio groups and checkboxes One can make a readonly field look normal with the tsnolock classname Text Multi Text Multi Date Multi Textarea Multi Textarea More Multi Textarea Select Multi One Two Three Select Multi One Two Three Multiselect multi One Two Three Four Five Cool apply changes Multiselect multi One Two Three Four Five Cool apply changes Errors Info Error Text An explanation of the error in question Another explanation of the error in question Info Text An information about the field Another information about the field Disabled info Text An information about the field Another information about the field Forms in Asides Check out the Form in that Aside Open the Aside Colored Forms Choose your color Dark Red Green Blue Purple Yellow LiteWhite Text Select One Two Three Date Text Textarea Textarea Select One Two Three Select multiple One Two Three Four Five Cool apply changes Date Radios Option One Option Two Checkbox I agree I dont agree Switch I agree I dont agree If you find a bug or need a feature Create GitHub Issue"},{"title":"","href":"components/forms/tabs.html","content":""},null,null,{"title":"Header Buttons","href":"components/header/index.html","content":"Header buttons Go go gadget Header"},null,{"title":"Icons","href":"components/icons/css.html","content":"Icons buttonhover ibefore fontfamily Open Sans important fontweight 600 tsdoxtabs edbmldeclareedbmlZCEiMv0asfunction edbml use strict var out edbmlout txt edbmlsafetext val edbmlsafeattr tsiconlogot1 tsiconlogot2 tsicondiscovery tsiconactivity tsicontodo tsiconnetwork tsiconcreatedocument tsiconalldocuments tsicondocument tsiconsales tsiconpurchases tsicondrafts tsiconapps tsiconusersettings tsiconsettings tsiconcompanyprofile tsiconlogout tsiconsupport tsiconchecked tsiconaccept tsicondone tsiconcheckedalt tsiconremove tsiconadd tsiconclose tsiconlocation tsiconaddfilter tsiconfollowed tsiconunfollowed tsiconsearch tsiconstatuschange tsiconedit tsiconrating tsiconshare tsiconindustry tsiconshowpicker tsiconwarning tsicontimer tsiconcomment tsiconmore tsiconusers tsiconownership tsiconcompanysize tsiconview tsiconreject tsicondispute tsiconmenuswitch tsicondelete tsiconcancel tsiconinfo tsiconforums tsiconaddfield tsiconfileaccess tsiconerror tsiconappactivate tsiconappactive tsiconfileattach tsiconreset tsiconsend tsiconsave tsiconproceed tsiconback tsicondownload tsiconbroadcastmessage tsiconinsertfrominventory tsicontriangleright tsicontriangleleft tsicontriangleup tsicontriangledown tsiconarrowright tsiconarrowleft tsiconarrowup tsiconarrowdown tsiconpreview tsiconlocked tsiconunlocked tsiconnext tsiconapprove tsiconcode tsiconhalt tsiconpay tsiconother tsiconmyapps tsiconcompanyevent tsiconsplit tsiconmerge tsiconassociated tsiconradio tsiconradioon tsiconcheckbox tsiconcheckboxon tsiconcheckboxindeterminate tsiconwrittenrequest tsiconcategories tsiconfavorites tsiconheart tsiconpreferred tsiconpin tsiconpreviouslyrequested tsiconcart tsiconarchive tsiconaddtoarchive tsiconcalendar tsiconselect tsiconcollaboration tsiconaddcurrentobject tsiconforward tsiconquestion tsiconphone tsiconbox tsiconusersassign tsiconusersadd tsiconusersremove sortforEachfunctionicon outhtml txticon return outwrite "},{"title":"Icons","href":"components/icons/iconspirit.html","content":"IconsSpirit This spirit is only used in Docs for now We should probably make this into a screenshot page This is a good old CSS icon We must always remember that the icon remains centered in the list item as the text wraps to multiple lin This icon is embedded via inline SVG As you can see the icon still remains centered vertically when the text wraps to multiple line This icon is loaded from external bundle 1 This icon is loaded from external bundle 1 This icon is loaded from external bundle 1 This icon is loaded from external bundle 2 This icon is loaded from external bundle 2 This icon is loaded from external bundle 2 If you find a bug or need a feature Create GitHub Issue"},{"title":"Icons","href":"components/icons/index.html","content":"Icons A library of icons that work great with Buttons Assign any of the icon classnames to an i element to get an icon Note that we like to reserve i for icons so if you need to emphasize text consider using em If you find a bug or need a feature Create GitHub Issue"},null,{"title":"Icons","href":"components/icons/list.html","content":"Icons tsdoxtabs Icons This is the definitive list of all supported icons There are 3 sizes displayed for each icon tsfontsizesmall 11px This size is used when an icon is attached to a form field tsfontsizeicon 22px This size is used most of the time when displaying icons 36px This size isnt used directly on the pages but its common to use icons on this size in the App Store icons of Apps tsuireadyfunction function geticontype color dark return item Icon type type color color function geticonrowtype description return geticontype geticontype geticontype type description var table tsuigeticons tablecols label 11px type iconssizetiny minwidth tsuiUNIT 3 tsfontsizeicon label 22px type iconssizestd minwidth tsuiUNIT 3 App Icon Size label 36px type iconssizeapp minwidth tsuiUNIT 3 label Classname type tstext flex 3 minwidth 200 label Description type tstext flex 10 minwidth 200 wrap true tablerows geticonrowtsicondiscovery Some horrible cool description goes here with MARKDOWN supportn Fulln Onn Awesome geticonrowtsiconactivity geticonrowtsicontodo geticonrowtsiconnetwork geticonrowtsiconcreatedocument geticonrowtsiconalldocuments geticonrowtsicondocument geticonrowtsiconsales geticonrowtsiconpurchases geticonrowtsicondrafts geticonrowtsiconapps geticonrowtsiconusersettings geticonrowtsiconsettings geticonrowtsiconcompanyprofile geticonrowtsiconlogout geticonrowtsiconsupport geticonrowtsiconchecked geticonrowtsiconaccept geticonrowtsicondone geticonrowtsiconcheckedalt geticonrowtsiconremove geticonrowtsiconquestion geticonrowtsiconmore geticonrowtsiconinfo geticonrowtsiconadd geticonrowtsiconclose geticonrowtsiconlocation geticonrowtsiconaddfilter geticonrowtsiconfollowed geticonrowtsiconunfollowed geticonrowtsiconsearch geticonrowtsiconstatuschange geticonrowtsiconedit geticonrowtsiconrating geticonrowtsiconshare geticonrowtsiconindustry geticonrowtsiconshowpicker geticonrowtsiconwarning geticonrowtsicontimer geticonrowtsiconcomment geticonrowtsiconusers geticonrowtsiconownership geticonrowtsiconcompanysize geticonrowtsiconview geticonrowtsiconreject geticonrowtsicondispute geticonrowtsiconmenuswitch geticonrowtsicondelete geticonrowtsiconcancel geticonrowtsiconforums geticonrowtsiconaddfield geticonrowtsiconfileaccess geticonrowtsiconerror geticonrowtsiconappactivate geticonrowtsiconappactive geticonrowtsiconfileattach geticonrowtsiconreset geticonrowtsiconsend geticonrowtsiconsave geticonrowtsiconproceed geticonrowtsiconback geticonrowtsicondownload geticonrowtsiconbroadcastmessage geticonrowtsiconinsertfrominventory geticonrowtsicontriangleright geticonrowtsicontriangleleft geticonrowtsicontriangleup geticonrowtsicontriangledown geticonrowtsiconarrowright geticonrowtsiconarrowleft geticonrowtsiconarrowup geticonrowtsiconarrowdown geticonrowtsiconpreview geticonrowtsiconlocked geticonrowtsiconunlocked geticonrowtsiconnext geticonrowtsiconapprove geticonrowtsiconcode geticonrowtsiconhalt geticonrowtsiconpay geticonrowtsiconother geticonrowtsiconmyapps geticonrowtsiconcompanyevent geticonrowtsiconsplit geticonrowtsiconmerge geticonrowtsiconassociated geticonrowtsiconradio geticonrowtsiconradioon geticonrowtsiconcheckbox geticonrowtsiconcheckboxindeterminate geticonrowtsiconcheckboxon geticonrowtsiconwrittenrequest geticonrowtsiconcategories geticonrowtsiconfavorites geticonrowtsiconheart geticonrowtsiconpreferred geticonrowtsiconpin geticonrowtsiconpreviouslyrequested geticonrowtsiconcart geticonrowtsiconarchive geticonrowtsiconaddtoarchive geticonrowtsiconcalendar geticonrowtsiconselect geticonrowtsiconcollaboration geticonrowtsiconaddcurrentobject geticonrowtsiconforward geticonrowtsiconphone geticonrowtsiconbox geticonrowtsiconusersassign geticonrowtsiconusersadd geticonrowtsiconusersremove "},null,null,{"title":"","href":"components/icons/tabs.html","content":""},{"title":"Inline Components","href":"components/index.html","content":"Inline Components tsdoxtabs Inline components These components depend on special markup structures and some may expose features though a JavaScript API Other than specifying the datats attribute as shown there is no need to initialize the components in any special way Button A true classic available in several flavors Primary Secondary Tertiary Primary Secondary Tertiary Primary Secondary Tertiary Primary Secondary Tertiary Primary Secondary Tertiary Primary Secondary Tertiary CompanyCard A unified way to show companies id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Tradeshift logo assetslogopng size 100249 location San Francisco California industry Software IT connection 2 id 6bf17754f9de4e31aa31bd3ff765b9c2 data name Tradeshift logo assetslogopng size 100249 location San Francisco California industry Software IT connection 2 Form Another classic cant have webapps without them Text Text Text Textarea Textarea Textarea Date Date Date Select One Two Three Select One Two Three Select One Two Three Select multiple One Two Three Four Five Cool apply changes Select multiple One Two Three Four Five Cool apply changes Select multiple One Two Three Four Five Cool apply changes Choose wisely Red pill Blue pill Choose wisely Red pill Blue pill Choose wisely Red pill Blue pill Legally Binding Contract I agree to something I agree to something by default Legally Binding Contract I agree to something I agree to something by default Legally Binding Contract I agree to something I agree to something by default Settings Page Secret Feature Secret Feature On by default Settings Page Secret Feature Secret Feature On by default Settings Page Secret Feature Secret Feature On by default Icons We support a range of icons Here are a few randomly selected ones Menu Not to be confused with the main navigation this is simply a list of selectable items I have an icon on my right And a second line I have an icon on my left but skipped the second line I have an icon on my right And a second line I have an icon on my left but skipped the second line I have an icon on my right And a second line I have an icon on my left but skipped the second line Note A nice way to inform the user about something on the page This is not for status messages It also works on pagelevel You love the Note You love the Note You love the Note Search Unified search experience TabBar An easy way to show tabs Also works on pagelevel var tabbar tsuigettabbarexample tabbartabs label Tab One onselect function tsuiNotificationsuccessthislabel label Tab Two onselect function tsuiNotificationsuccessthislabel var tabbar tsuigettabbarexample tabbartabs label Tab One onselect function tsuiNotificationsuccessthislabel label Tab Two onselect function tsuiNotificationsuccessthislabel guiBroadcastaddguiBROADCASTDIDSPIRITUALIZE onbroadcast function var firstload true var tabbar tsuigettabbarexample tabbartabs label Tab One onselect function if firstload firstload false else tsuiNotificationsuccessthislabel label Tab Two onselect function tsuiNotificationsuccessthislabel Table Ranging from spreadsheetstyle editing to just showing some tabular data var table tsuigettableexample tablecols label Level type tsnumber label Character flex 2 label Alignment flex 2 tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil var table tsuigettableexample tablecols label Level type tsnumber label Character flex 2 label Alignment flex 2 tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil guiBroadcastaddguiBROADCASTDIDSPIRITUALIZE onbroadcast function var table tsuigettableexample tablecols label Level type tsnumber label Character flex 2 label Alignment flex 2 tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil Time Human readable time formatting UserImage Little avatars for the users "},{"title":"Menu","href":"components/menus/index.html","content":"Menu Not to be confused with the main navigation the tsmenu is simply a list of selectable items Assign datatsMenu to a menu element to initialize it as a Menu Use li elements to separate the menu items all of which follows the structure of a Button Item One Item Two Item Three Item One Item Two Item Three Item One Item Two Item Three Adding Icons The markup follows the convention for buttons Use a span and an i element to seperate text and icon simply reverse the two to make the icon go first I have an icon on my right I have an icon on my left I have an icon on my right I have an icon on my left I have an icon on my right I have an icon on my left Using the second linesub text To add a second line to the Menu item just add a sub with some text in it Im the first line Im the second line Im the first line Im the second line Im the first line Im the second line Select one To create a single select menu mark one and only one li with the tschecked classname and use the tsiconchecked classname for the icon i element Selected Not selected Selected Not selected Selected Not selected Select many To create a multi select menu simply add more classnames and icons Selected Also Selected Selected Also Selected Selected Also Selected The UI component makes no attempt to automatically manage these icons and classnames whenever a new menu item gets selected Disabled items You can mark any selection as readonly by adding the disabled attribute to the individual buttons Not selected Not selected Selected Not selected Not selected Selected Not selected Not selected Selected If you find a bug or need a feature Create GitHub Issue"},null,{"title":"","href":"components/modals/page1.html","content":"Pa"},{"title":"","href":"components/modals/page2.html","content":"Pa"},{"title":"Note","href":"components/notes/index.html","content":"Note You can use the Note to give information to the user about the whole page or a section of the page The Note should however not be used to display errors or warning messages please use the Notification for that To explain to the user what the page is about you can show a Note at the top Note that there should never be more than one pagelevel Note tsuiNote icon tsiconheart text This page explains how to use the Note component with some nice examples onclose function tsuiNotificationsuccessThe Note is gone tsuiNote icon tsiconheart text This page explains how to use the Note component with some nice examples onclose function tsuiNotificationsuccessThe Note is gone You can add buttons to the Note If you save a reference to the Note you can close it with any button var note tsuiNote buttons label Button type tsprimary onclick function noteclose var note tsuiNote buttons label Button type tsprimary onclick function noteclose You can also add some links via Markdown When a link is clicked the URL will be passed along to the onlink method As you can see below the URL can be just a key it doesnt have to be real URL tsuiNote text Choose link oneONE or twoTWO or threeTHREE onlink functionurl tsuiNotificationsuccessurl thisclose tsuiNote text Choose link oneONE or twoTWO or threeTHREE onlink functionurl tsuiNotificationsuccessurl thisclose If the link should indeed link to something make sure to provide the full protocol https Notes should not be used for internal navigation at least not yet You can use an inline Note to give information about a certain section of the page Only the pagelevel Note is closeable while inline Notes should stay on the page with the content You love the Note You love the Note Note without icon using simple HTML This is the iconless Note This is the iconless Note Inline Note with closeable function This is the closeable inline Note This is the closeable inline Note The Note will wrap to multiple lines if theres a lot of content inside Arcane spell failure charm domain cover dragon type enemy experience points versus Tradeshift family domain fighter and hardness hit die initiative check intelligence melee attack roll miniature figure movement modes Party planning domain point of origin powerful charge ray regeneration rogue special quality speed take 20 touch attack turned Fivefoot step ability class feature domain dying level luck domain negate ranged touch attack result speed surprise target total concealment unarmed strike Armor class base save bonus check conjuration divine spell falling objects fly law domain school of Tradeshift shield bonus threatened square war domain Ability damage acid effects burrow chaos domain class feature darkvision fullround action glamer subschool good subtype improved evasion incorporeal subtype ocean domain platinum piece size modifier You can use a Note in an Aside or a SideBar if you put the inline note as the first child of the tspanel Note in the Aside Note in the Aside If you find a bug or need a feature Create GitHub Issue"},{"title":"Notification","href":"components/notifications/index.html","content":"Notification Simple modals for providing users with notifications much like the JavaScript alert method Basic markdown may be used for links and formatting The success notification demands no user interaction tsuiNotificationsuccessYou did it tsuiNotificationsuccessYou did it The info warning and error notification must be accepted by the user tsuiNotificationinfoYou can do it tsuiNotificationwarningYou will fail tsuiNotificationerrorYou are wrong tsuiNotificationinfoYou can do it tsuiNotificationwarningYou will fail tsuiNotificationerrorYou are wrong An optional second argument specifies the button text tsuiNotificationwarningBeware Understood tsuiNotificationwarningBeware Understood You can configure a callback for when the Notification gets accepted tsuiNotificationinfoYou must accept it onaccept function tsuiNotificationsuccessWe knew you would tsuiNotificationinfoYou must accept it onaccept function tsuiNotificationsuccessWe knew you would Notifications support basic markdown for formatting and links Markdown for bold text and italic text and source code Markdown for a hyperlinkhttpwwwexamplecom When a link is clicked the URL will be passed along to the onlink method As you can see below the URL can be just a key it doesnt have to be real URL var text Choose link oneONE or twoTWO or threeTHREE tsuiNotificationinfotext onlink functionurl thisacceptthenfunction onfadeout tsuiNotificationsuccessurl var text Choose link oneONE or twoTWO or threeTHREE tsuiNotificationinfotext onlink functionurl thisacceptthenfunction onfadeout tsuiNotificationsuccessurl If the link should indeed link to something make sure to provide the full protocol https tsuiNotificationinfo Please visit Tradeshifthttpwwwtradeshiftcom tsuiNotificationinfo Please visit Tradeshifthttpwwwtradeshiftcom Note that all links will open in a new tab or window depending on the browser settings so you should not use links in Notifications for internal navigation at least not just yet If you find a bug or need a feature Create GitHub Issue"},{"title":"Pager","href":"components/pager/index.html","content":"Pager Provides a navigation menu with shortcuts for all kinds of paginated data Assign datatsPager to a menu or nav to initialize it as a Pager The component may be configured in HTML complete with an inline callback like in this example or you can configure it via a JavaScript API like in this example tsuigetmypager pager pagerpages 8 pagerpage 0 pageronselect functionpage consolelogpage tsuigetmypager pager pagerpages 8 pagerpage 0 pageronselect functionpage consolelogpage As you can see the Pager has no default outline and this will make it easier to embed into other components Heres a short summary of the Pagers properties and methods If you find a bug or need a feature Create GitHub Issue"},{"title":"Panels","href":"components/panels/index.html","content":" "},{"title":"Search","href":"components/search/index.html","content":"Search The Search is prominently featured in the Main ToolBar but you can use it anywhere on the page if you like Note that the API is in any case identical You can initialize a Search with datatsSearch The classname tsinset will add an outline so that we can see how it behaves on this white background The search field expands when the field is focused by the user or whenever theres a nonempty value in the field You can change the value like this var search tsuigetmysearch searchvalue Hello world var search tsuigetmysearch searchvalue Hello world To keep the field expanded at all times simply assign the CSS classname tsexpanded Search info The datatsinfo attribute works to show a title mouseover tooltip when the field is collapsed and a placeholder when the field is expanded Search callbacks The onsearch callback gets invoked when when the user presses ENTER var search tsuiToolBarsearch searchvalue Press ENTER here searchonsearch functionvalue tsuiNotificationsuccessvalue Search cleared var search tsuiToolBarsearch searchvalue Press ENTER here searchonsearch functionvalue tsuiNotificationsuccessvalue Search cleared If defined the onidle method gets called whenever the user pauses typing var search tsuiToolBarsearch searchvalue Try it now searchonidle functionvalue tsuiNotificationsuccessvalue var search tsuiToolBarsearch searchvalue Try it now searchonidle functionvalue tsuiNotificationsuccessvalue The onidle method may also be called when the field loses focus The idletime property controls the timeout value default is 500 milliseconds Here an overview of the properties and methods of the Search component If you find a bug or need a feature Create GitHub Issue"},{"title":"SideBars","href":"components/sidebars/index.html","content":"SideBars used to test that sidebars can be transferred from MAIN to BODY without breaking functionality since this always happens in V4 if false documentreadyfunction var elem mysidebar var main elemclosesttsmain alertmainget0 if mainlength 0 mainafterelem used to test delayed Angular initialization in Collaboration panel note that the title must also be removed to simulate collaboration if false documentreadyfunction setTimeoutfunction var elem mysidebar elemattrdatatsautoclose false 1000 tsdoxtabs SideBar The SideBar is a panel used for interactions directly related to the main content such as filtering and sorting a list of items Assign datatsSideBar to an aside to initialize as a SideBar The SideBar must be created with a child Panel SideBar content Also note tht the SideBar must be positioned before or after the Main element Toggle the SideBar In mobile breakpoint the SideBar is hidden and must be toggled forth manually If you resize to mobile view you can try it with this button Toggle SideBar You can toggle the SideBar like you would toggle an Aside var sidebar guigetmysidebar sidebaropen sidebarclose sidebartoggle Bonus panels You can put a Footer next to the Panel The Footer will stick to the bottom of the SideBar If you want this to be visible in mobile only as the current designs suggest you can assign it the classname tsshowmobileonly Nesting Asides You can make subsidebars by nesting Aside components in the tssidebar The Aside can be opened and closed like a normal Aside SideBar content Aside content Custom toolbar buttons The SideBar header works like a Toolbar You can add buttons with an API so well add a button to toggle that Aside we talked about var sidebar guigetmysidebar var header sidebarheader headerbuttonspush icon tsiconadd onclick function guigetmyasidetoggle var sidebar guigetmysidebar var header sidebarheader headerbuttonspush icon tsiconadd onclick function guigetmyasidetoggle This API is likely to change SideBar content Aside content Footer content The button below is only relevant in mobile view Toggle SideBar"},{"title":"","href":"components/sidebars/tabs.html","content":""},null,{"title":"Spinner","href":"components/spinners/index.html","content":"Spinner function spinelm elmattrdatatsbusy true setTimeoutfunction elmattrdatatsbusy false 1500 Spinner The Spinner can be used with Main Aside Table SideBar and Button You can assign the datatsbusy to the Main element to initialize a Spinner Main content Lets try that with jQuery var main mainfirst mainattrdatatsbusy Crunching data setTimeoutfunction mainattrdatatsbusy 1500 var main mainfirst mainattrdatatsbusy Crunching data setTimeoutfunction mainattrdatatsbusy 1500 If you want a blocking overlay you can use the datatsblocking attribute var main mainfirst mainattrdatatsblocking Crunching and blocking setTimeoutfunction mainattrdatatsblocking 1500 var main mainfirst mainattrdatatsblocking Crunching and blocking setTimeoutfunction mainattrdatatsblocking 1500 Aside and SideBar Assign the datatsbusy attribute to an Aside or SideBar to initialize a Spinner Aside content It will look like this var aside myaside asideattrdatatsopen true asideattrdatatsbusy Crunching data setTimeoutfunction asideattrdatatsbusy setTimeoutfunction asideattrdatatsopen false 250 1500 var aside myaside asideattrdatatsopen true asideattrdatatsbusy Crunching data setTimeoutfunction asideattrdatatsbusy setTimeoutfunction asideattrdatatsopen false 250 1500 Button Assign the datatsbusy attribute to a Button to initialize a Spinner Primary Show Spinner Table Assign the datatsbusy attribute to a Table to initialize a Spinner tsuigetmytable table tablecolsOne Two Tree tablerows A D G B E H C F I mytableattrdatatsbusy Loading setTimeoutfunction mytableattrdatatsbusy 1500 tsuigetmytable table tablecolsOne Two Tree tablerows A D G B E H C F I mytableattrdatatsbusy Loading setTimeoutfunction mytableattrdatatsbusy 1500 Aside content"},{"title":"Table Actions","href":"components/table/actions.html","content":"Selection actions The table actions are reserved for working with selections They work much like the buttons except the icon should never be omitted from an action since it is always displayed and not just in mobile breakpoint You can try to select something in this table var table tsuigettable1 tablecolsOne Two Threerows A B C D E F G H I selectableupdate function update var actions tableactions var maximum tablerowslength var counter tableselectedlength ifcounter 0 tablestatuscounter of maximum rows selected ifactionslength actionspush label Delete icon tsicondelete label Report icon tsiconhalt label Revert icon tsiconback onclick consolelogThe revert action was clicked else actionsclear tablestatusmaximum rows update var table tsuigettable1 tablecolsOne Two Threerows A B C D E F G H I selectableupdate function update var actions tableactions var maximum tablerowslength var counter tableselectedlength ifcounter 0 tablestatuscounter of maximum rows selected ifactionslength actionspush label Delete icon tsicondelete label Report icon tsiconhalt label Revert icon tsiconback onclick consolelogThe revert action was clicked else actionsclear tablestatusmaximum rows update The actions method both sets and gets the actions If you omit the argument youll get the current actions jQuery style You can use array methods like push pop shift unshift splice and so on to manage actions just note that the actions length is a readonly property Heres a summary of the actions collection and action model If you find a bug or need a feature Create GitHub Issue"},null,null,null,null,null,null,null,null,null,null,null,null,null,{"title":"Table Build","href":"components/table/building.html","content":"Table Build tsdoxtabs Building the Table You can build your cols and rows with a compact syntax tsuigetmytable table tablecolsOne Two Tree tablerows A D G B E H C F I tsuigetmytable table tablecolsOne Two Tree tablerows A D G B E H C F I You can also declare columns as objects The objects have a label property tsuigetexample1 table tablecols label One label Two label Three tsuigetexample1 table tablecols label One label Two label Three This will come in handy when we need to assign extra properties to the columns If we set the type property to tsnumber the text will be rightaligned except in the first column tsuigetexample2 table tablecols label Type label Value type tsnumber tablerows Random number Mathrandom tsuigetexample2 table tablecols label Type label Value type tsnumber tablerows Random number Mathrandom We can also declare rows as objects with a list of cells This syntax will allow us to mark the row as selected you can read more about selection tsuigetexample3 table tableselectablerows cells A D G selected true cells B E H cells C F I tsuigetexample3 table tableselectablerows cells A D G selected true cells B E H cells C F I The individual cells can also be declared as objects if the displayed text should be different from the hidden value which can be anything you like tsuigetexample4 table tablerows cells value 1 text One value 2 text Two value 3 text Three tsuigetexample4 table tablerows cells value 1 text One value 2 text Two value 3 text Three You can update a single row whenever you like Here with compact syntax tsuigetexample5 table tablerows A B C D E F tablerow1 Mathrandom Mathrandom Mathrandom tsuigetexample5 table tablerows A B C D E F tablerow1 Mathrandom Mathrandom Mathrandom You can of course also update a single cell Here with compact syntax tsuigetexample6 table tablerows A B C D E F tablecell1 1 Mathrandom tsuigetexample6 table tablerows A B C D E F tablecell1 1 Mathrandom You can use array methods like push pop shift unshift splice reverse and so on to mange the rows Just note that the length property is readonly tsuigetexample7 table var rows tablerows rowspush1 2 3 rowsunshift4 5 6 rowssplice0 0 7 8 9 rowsreverse tsuigetexample7 table var rows tablerows rowspush1 2 3 rowsunshift4 5 6 rowssplice0 0 7 8 9 rowsreverse Here a summary of the methods that deal with building the Table"},{"title":"Table Buttons","href":"components/table/buttons.html","content":"Table buttons The Table supports buttons and we will soon add some futher documentation For now we will simply recommend that you dont use buttons unless the Table is maximized This feature however also doesnt have any documentation var table tsuigettable1 tablecolsOne Two Threerows A B C D E F G H I buttons label One type tsprimary label Two type tssecondary label Three onclick consolelogThe tertiary button was clicked var table tsuigettable1 tablecolsOne Two Threerows A B C D E F G H I buttons label One type tsprimary label Two type tssecondary label Three onclick consolelogThe tertiary button was clicked The buttons method both sets and gets the buttons If you omit the argument youll get the current actions jQuery style You can use array methods like push pop shift unshift splice and so on to manage buttons just note that the buttons length is a readonly property TODO The Table breakpoint should be local to the Table not the window If you find a bug or need a feature Create GitHub Issue"},{"title":"Table Click","href":"components/table/clicking.html","content":"Table Click tsdoxtabs Clicking the cells You can make the Table body clickable The rowindex and cellindex refer to the indexes in the JSON arrays and not the table as shown on the screen They are in other words not affected by sorting and paging and searching var popup tsuiNotification tsuigetexample8 table tablerows A D G B E H C F I tableclickablefunctionrowindex cellindex popupsuccessRow rowindex Cell cellindex var popup tsuiNotification tsuigetexample8 table tablerows A D G B E H C F I tableclickablefunctionrowindex cellindex popupsuccessRow rowindex Cell cellindex "},{"title":"Table Collaboration","href":"components/table/collaborate.html","content":"Table Collaboration tsdoxtabs Table Collaboration This API is likely to change at some point You can activate a dedicated collaboration button in the statusbar var popup tsuiNotification tsuigettable1 table tablecollabbuttonfunction onclick popupsuccessGo collaborate colsA B C Drows 1 4 7 10 2 5 8 11 3 6 9 12 var popup tsuiNotification tsuigettable1 table tablecollabbuttonfunction onclick popupsuccessGo collaborate colsA B C Drows 1 4 7 10 2 5 8 11 3 6 9 12 The button triggers a callback but there is no default behavior associated The API to initialize and resume a Collaboration thread will be defined elsewhere When you are done with the button you can hide it again tsuigettable1collabbuttonnull tsuigettable1collabbuttonnull"},{"title":"Table Config","href":"components/table/configuring.html","content":"Table Config tsdoxtabs Configuring the Table You can make the table configurable by a button in the statusbar var popup tsuiNotification tsuigettable1 table tableconfigbuttonfunction onclick popupsuccessGo configure colsA B C Drows 1 4 7 10 2 5 8 11 3 6 9 12 var popup tsuiNotification tsuigettable1 table tableconfigbuttonfunction onclick popupsuccessGo configure colsA B C Drows 1 4 7 10 2 5 8 11 3 6 9 12 The button triggers a callback but there is otherwise no default UI associated Since the visibility of columns is always a candidate for configuration the ColModel supports a visible property that can be used to hide columns tsuigettable1 table var cols tablecols function hideindex colsindexvisible false ifindex setTimeoutfunction next hideindex 1000 3 tsuigettable1 table var cols tablecols function hideindex colsindexvisible false ifindex setTimeoutfunction next hideindex 1000 3 Heres a summary of these things"},{"title":"Table Demo","href":"components/table/demo.html","content":"Table Demo tsmain overflowy hidden tsdoxtabs"},null,{"title":"Table Edit","href":"components/table/editing.html","content":"Table Edit tsdoxtabs Editing the cells We can make the Table editable with a callback that fires on change tsuigettable1 table tablerows Single asterisks is used for italic text Double asterisks is used for strong text Single backtick is used for monotype text Double tilde can be used to Strike text editablefunction oneditrowindex cellindex value consolelogSend to backend value tablecellrowindex cellindex value tsuigettable1 table tablerows Single asterisks is used for italic text Double asterisks is used for strong text Single backtick is used for monotype text Double tilde can be used to Strike text editablefunction oneditrowindex cellindex value consolelogSend to backend value tablecellrowindex cellindex value All cells are assumed editable unless negated in the column definition tsuigettable6 table tablecols label Edit label Edit label Dont edit editable false rows V V X editablefunction oneditri ci value thiscellri ci value tsuigettable6 table tablecols label Edit label Edit label Dont edit editable false rows V V X editablefunction oneditri ci value thiscellri ci value If you switch to verbose syntax you can also disable editing per row tsuigettable7 table tablerows cells X X X editable false cells V V V cells V V V editablefunction oneditri ci value thiscellri ci value tsuigettable7 table tablerows cells X X X editable false cells V V V cells V V V editablefunction oneditri ci value thiscellri ci value You can override both columns and rows by specifying editabletrue on the individual cells Again this would best be done using verbose syntax Multiline editing You can enter newlines by holding SHIFT on ENTER You will need to enter two newlines to create a paragraph Note however that we only show the first paragraph unless the column is set to wrap var popup tsuiNotification tsuigettable8 table tablecols label Wrapped column wrap true label Unwrapped column rows Hold SHIFT while pressing ENTER to add a second paragraph New paragraph ignored editablefunction oneditri ci value tablecellri ci value var popup tsuiNotification tsuigettable8 table tablecols label Wrapped column wrap true label Unwrapped column rows Hold SHIFT while pressing ENTER to add a second paragraph New paragraph ignored editablefunction oneditri ci value tablecellri ci value Input validation Note that the actual update is a manual proces This will give you a break to validate the input In this example well show the errors in a Notification var popup tsuiNotification tsuigettable2 table tablerows 1 1 2 3 5 8 13 21 34 55 editablefunction oneditri ci value value Numbervalue ifisNaNvalue tableinvalidri ci popuperrorPlease type a number onaccept function tablefocusri ci else consolelogSend to backend value tablecellri ci value var popup tsuiNotification tsuigettable2 table tablerows 1 1 2 3 5 8 13 21 34 55 editablefunction oneditri ci value value Numbervalue ifisNaNvalue tableinvalidri ci popuperrorPlease type a number onaccept function tablefocusri ci else consolelogSend to backend value tablecellri ci value We can report the errors in a less annoying way if we pass a string as we mark the cells invalid The message will show in the statubar when the cell is focused Well also initialize the statusbar with an empty string so that it doesnt awkwardly pop into existance function formatvalue return new DatevaluetoDateString function validvalue return isNaNnew DatevaluegetTime tsuigettable3 table tablestatusrows value 19851026 text format19851026 value 20151021 text format20151026 value 19551112 text format19551112 editablefunction oneditri ci value ifvalidvalue consolelogSend to backend value tablecellri ci value value text formatvalue else var message Please use the format YYYYMMDD tableinvalidri ci message function formatvalue return new DatevaluetoDateString function validvalue return isNaNnew DatevaluegetTime tsuigettable3 table tablestatusrows value 19851026 text format19851026 value 20151021 text format20151026 value 19551112 text format19551112 editablefunction oneditri ci value ifvalidvalue consolelogSend to backend value tablecellri ci value value text formatvalue else var message Please use the format YYYYMMDD tableinvalidri ci message When the cell is eventually updated it automatically becomes valid Lets talk more about the difference between text and value in the example above Text versus value It doesnt always matter but its important to note that we edit the value while we show the text Heres another example to illustrate the difference tsuigettable4 table tablerows value 1000 text 100000 value 2000 text 200000 value 3000 text 300000 editable tsuigettable4 table tablerows value 1000 text 100000 value 2000 text 200000 value 3000 text 300000 editable This way we can edit validate and persist the data in a uniform format in this case JavaScript numbers while displaying a regionalized or otherwise customized format We can exploit this creatively by editing a document ID and showing the document title for example Remember to update verbosely tablecellrowindex cellindex text 400000 value 4000 because otherwise the text becomes identical to the value Also note that the editable callback will always serve the value as a string so it may be nescessary to convert it to a number Heres the more complete example function formatn return ntoFixed2replaceBd3dg tsuigettable5 table tablerows value 1000 text format1000 value 2000 text format2000 value 3000 text format1000 editablefunctionri ci value value Numbervalue ifisNaNvalue tableinvalidri ci else tablecellri ci value value text formatvalue function formatn return ntoFixed2replaceBd3dg tsuigettable5 table tablerows value 1000 text format1000 value 2000 text format2000 value 3000 text format1000 editablefunctionri ci value value Numbervalue ifisNaNvalue tableinvalidri ci else tablecellri ci value value text formatvalue Heres an overview of the editing related features API for knowing when something is invalid everything is valid How to visually differentiate editable versus noneditable cells"},{"title":"Table Extras","href":"components/table/extras.html","content":"Table Extras function getbuttonlabel name value return item Button type tssecondary tsmicro label label name name value value function getswitchname value checked return item Switch name name value value checked checked function geticontype color return item Icon type type color color black function getimagesrc width height return item Image src src width width 100 height height 100 background true function getuserimagename src return item UserImage name name src src tsdoxtabs Table extras Table cells can be declared via JSON using verbose syntax But we can use a different JSON syntax to declare cells with special content The Table will generate components based on the value of the item property and this can be one of the following Button Icon Image Switch UserImage Button This function will return the JSON to generate a Button in the Table function getbuttonlabel name value return item Button type tssecondary tsmicro label label name name value value To conserve browser memory in very large Tables the onclick callback is not supported But you can intercept the Button click via the name and value property you just need to assign the onbutton method to the Table tsuigettable1 table tablerows Apple getbuttonBuy this Apple buy 123 Orange getbuttonBuy that Orange buy 456 Banana getbuttonBuy the Banana buy 789 tableonbutton functionname value rowindex cellindex ifname buy tsuiNotificationsuccessProduct value ordered tablecellrowindex cellindex getbuttonCancel order tsuigettable1 table tablerows Apple getbuttonBuy this Apple buy 123 Orange getbuttonBuy that Orange buy 456 Banana getbuttonBuy the Banana buy 789 tableonbutton functionname value rowindex cellindex ifname buy tsuiNotificationsuccessProduct value ordered tablecellrowindex cellindex getbuttonCancel order The Button value can be anything from strings and numbers and booleans to objects and arrays if that helps Just dont assign any functions because those will be ignored The value also doubles as a sorting criteria of the column is sortable so bear that in mind Here are the configurable properties of the ButtonModel Icon This function returns the JSON to generate an icon function geticontype color black return item Icon type type color color The type configures the icon classname and the optional color property can be one of black medium red green blue and purple tsuigettable3 table tablerows geticontsiconsales geticontsiconcancel medium geticontsiconerror red geticontsiconaccept green geticontsiconinfo blue geticontsiconfavorites purple tsuigettable3 table tablerows geticontsiconsales geticontsiconcancel medium geticontsiconerror red geticontsiconaccept green geticontsiconinfo blue geticontsiconfavorites purple Here are the configurable properties of the IconModel This interface may change as we upgrade to SVG icons Image This function returns the JSON to generate an Image function getimagesrc width height return item Image src src width width 100 height height 100 Note that the width and height properties are mandatory for us to fix the dimensions of the image even before it is loaded This will prevent the page from jumping around tsuigettable4 table tablerows getimageassetsimage1jpg getimageassetsimage2jpg getimageassetsimage3jpg getimageassetsimage4jpg tsuigettable4 table tablerows getimageassetsimage1jpg getimageassetsimage2jpg getimageassetsimage3jpg getimageassetsimage4jpg We can also declare a boolean property background in the JSON If set to true the image will be rendered as a backgroundimage to unlock further processing via CSS for example via the backgroundsize property Here are the configurable properties Switch This function returns the JSON to generate a Switch function getswitchname value checked return item Switch name name value value checked checked The Switch is the checkbox that looks like some kind of switch tsuigettable2 table tablerows Spam mails getswitchtoggle 123 true Prank calls getswitchtoggle 456 true House visits getswitchtoggle 789 false tableonswitch functionname value checked rowindex cellindex ifname toggle var status checked enabled disabled tsuiNotificationsuccessService value status tsuigettable2 table tablerows Spam mails getswitchtoggle 123 true Prank calls getswitchtoggle 456 true House visits getswitchtoggle 789 false tableonswitch functionname value checked rowindex cellindex ifname toggle var status checked enabled disabled tsuiNotificationsuccessService value status TODO We could need a layout feature to fix the width of the switch column Here are the configurable properties of the SwitchModel UserImage This function returns the JSON to generate a UserImage function getuserimagename src return item UserImage name name src src If you like you can also specify a size to adjust the width and height of the image tsuigettable5 table tablerows getuserimageJim Bob Johnson assetsjimpng getuserimageKarl Benson getuserimageMarshall Garrett getuserimageKelvin Castro tsuigettable5 table tablerows getuserimageJim Bob Johnson assetsjimpng getuserimageKarl Benson getuserimageMarshall Garrett getuserimageKelvin Castro Here are the properties of the UserImage"},{"title":"Table Filter","href":"components/table/filtering.html","content":"Table Filter tsdoxtabs Filtering the columns The table doesnt really know anything about filtering but it does support a button which can be assigned an icon and an onclick method Perhaps you can use this to create your own filtering UI in an Aside or something var table tsuigettable1 var popup tsuiNotification tablecols label Hello type tsnumber button icon tsiconaddfilter onclick function thisicon tsicondelete popupsuccessClicked var table tsuigettable1 var popup tsuiNotification tablecols label Hello type tsnumber button icon tsiconaddfilter onclick function thisicon tsicondelete popupsuccessClicked You can change the icon and the onclick method as often as you like var table tsuigettable1 var popup tsuiNotification var mycol tablecols0 mycolbuttonicon tsiconview mycolbuttononclick function popupsuccessClicked again var table tsuigettable1 var popup tsuiNotification var mycol tablecols0 mycolbuttonicon tsiconview mycolbuttononclick function popupsuccessClicked again When you implement filtering you can either build the rows from scratch or update the visible property of the existing row like in this example var table tsuigettable2 var popup tsuiNotification var isodd false tablerows1 2 3 4 5 6 7cols label All numbers type tsnumber button icon tsiconaddfilter info Show odd rows onclick function isodd isodd thisicon isodd tsicondelete tsiconaddfilter thisinfo isodd Show all rows Show odd rows tablecols0label isodd Odd numbers All numbers tablerowsforEachfunctionrow i rowvisible isodd i 2 0 true var table tsuigettable2 var popup tsuiNotification var isodd false tablerows1 2 3 4 5 6 7cols label All numbers type tsnumber button icon tsiconaddfilter info Show odd rows onclick function isodd isodd thisicon isodd tsicondelete tsiconaddfilter thisinfo isodd Show all rows Show odd rows tablecols0label isodd Odd numbers All numbers tablerowsforEachfunctionrow i rowvisible isodd i 2 0 true The button gets hidden by the search because it doesnt look right to have both Let us know if that becomes a problem"},{"title":"Table Formatting","href":"components/table/formatting.html","content":"Table Formatting tsdoxtabs Formatting the cells The Table supports a simple subset of Markdown out of the box tsuigettable1 table tablerows Italic text Strong text Strike text monotype text tsuigettable1 table tablerows Italic text Strong text Strike text monotype text Use double newline n to render multiple paragraphs We also have UL lists tsuigettable2 table tablerows Para 1nnPara 2nnPara 3 Item 1n Item 2n Item 3 tsuigettable2 table tablerows Para 1nnPara 2nnPara 3 Item 1n Item 2n Item 3 To support links youll first need to call the linkable method just to remind yourself that you may now become exposed to phishing attacks tsuigettable3 table tablelinkable tablerows Please visit Tradeshifthttpwwwtradeshiftcom tsuigettable3 table tablelinkable tablerows Please visit Tradeshifthttpwwwtradeshiftcom When you link to something make sure to include the protocol https and note that links should not be used for internal navigation at least not just yet If the link should work more like a button you can intecept the click action with the onlink callback In this case you can use any string as the href var popup tsuiNotification tsuigettable4 table tablelinkablefunction onlinkanystring popupsuccessanystring rows Choose link oneONE or twoTWO or threeTHREE var popup tsuiNotification tsuigettable4 table tablelinkablefunction onlinkanystring popupsuccessanystring rows Choose link oneONE or twoTWO or threeTHREE "},null,null,null,{"title":"Table","href":"components/table/index.html","content":"Table Contrary to common belief the datatsTable attribute should not be assigned to a table element because the component will create that table itself Instead we can assign it to a div All features are controlled through an API as outlined on the following pages If you find a bug or need a feature Create GitHub Issue"},{"title":"Table Layout","href":"components/table/layouting.html","content":"Layout the columns Columns sizes can flex relative to other columns These last two columns are twice the width of the first column which is assumed a flex value of 1 tsuigetexample4 table tablecols label Level type tsnumber label Character flex 2 label Alignment flex 2 tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil tsuigetexample4 table tablecols label Level type tsnumber label Character flex 2 label Alignment flex 2 tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil If the Table is small like in the example above you can still run into truncated text If this becomes a problem you can either wrap the column cells tsuigetexample5 table tablecols label Level type tsnumber label Character flex 2 wrap true label Alignment flex 2 tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil tsuigetexample5 table tablecols label Level type tsnumber label Character flex 2 wrap true label Alignment flex 2 tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil or you can assign it a minwidth in pixels If the table is big enough the flex values still count so we will leave them in noting that the first column is still assumed flex1 tsuigetexample6 table tablecols label Level type tsnumber minwidth 55 label Character flex 2 minwidth 300 label Alignment flex 2 tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil tsuigetexample6 table tablecols label Level type tsnumber minwidth 55 label Character flex 2 minwidth 300 label Alignment flex 2 tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil To ensure that the Table can work on a small screen or even a mobile phone you should strongly consider specifying a minwidth on all the columns On small screens this may result in a horizontal scrollbar but we dont consider this a problem for the Table A suggested feature creep would be to let the user control column visibility via the config button so that he can compare two columns without scrolling back and forth Finally theres an option to assign a fixed width to one or more columns This will override any flex It doesnt work if you assign it to all the columns so please dont do that tsuigetexample7 table tablecols label Level type tsnumber width 55 label Character minwidth 300 label Alignment tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil tsuigetexample7 table tablecols label Level type tsnumber width 55 label Character minwidth 300 label Alignment tablerows 21 Paladin Knight Lawful Good 13 Barbarian Queen Neutral Evil 11 Global Senior Vice President of Sales Chaotic Evil If you find a bug or need a feature Create GitHub Issue"},{"title":"Table Paging","href":"components/table/paging.html","content":"Table Paging tsdoxtabs Paging the rows You can limit the number of visible rows with the max method If the table contains more rows a Pager will be created An equivalent method size also fixes the height of the Table so that the pager footer never jump up and down getJSONassetsrowdatajson functionjson tsuigetexample9 table tablecols label ID type tsnumber label Name flex 2 label Price type tsnumber tablerowsjsonmax5 getJSONassetsrowdatajson functionjson tsuigetexample9 table tablecols label ID type tsnumber label Name flex 2 label Price type tsnumber tablerowsjsonmax5 You can track the page with the onpage method if for some reason you need that tableonpage functionindex consolelogindex called whenever the user changes page If you would like to manage paging yourself because you have a billion products and dont want to fetch them all at once you can create your own pager var popup tsuiNotification tsuigetbigdatatable table tablemax10cols label ID type tsnumber label Name flex 2 label Price type tsnumber tablepager pages 5 page 0 onselect loadpage function loadpageindex var url assetspage index json getJSONurl functionjson var n jsonlength popupsuccessLoaded n rows tablerowsjson loadpage0 var popup tsuiNotification tsuigetbigdatatable table tablemax10cols label ID type tsnumber label Name flex 2 label Price type tsnumber tablepager pages 5 page 0 onselect loadpage function loadpageindex var url assetspage index json getJSONurl functionjson var n jsonlength popupsuccessLoaded n rows tablerowsjson loadpage0 If you need to update the index later on for example to support history navigation it is recommended that you change the page property of the existing Pager instead of initializing a whole new Pager You can just call the same method without arguments mytablepagerpage 23"},{"title":"Table Search","href":"components/table/searching.html","content":"Searching the columns You can setup a SearchModel for any column via the search property We ship the Table with a builtin search mechanism but youll still need to call it The Table search method takes a column index and the string to search for getJSONassetsrowdatajson functionjson tsuigetexample10 table tablerowsjsonmax4cols label ID type tsnumber search tip Search product ID onidle functionvalue tablesearch0 value label Product Name flex 1 search tip Search product names onidle functionvalue tablesearch1 value getJSONassetsrowdatajson functionjson tsuigetexample10 table tablerowsjsonmax4cols label ID type tsnumber search tip Search product ID onidle functionvalue tablesearch0 value label Product Name flex 1 search tip Search product names onidle functionvalue tablesearch1 value The search algorithm is extremely primitive and to some degree it always will be at least until the Table can be loaded separately from other components because file size You can focus the search field if you like either by setting the focused property to true in the JSON or by calling the focus method sometime later on var table tsuigetexample10 tablecols1searchfocus var table tsuigetexample10 tablecols1searchfocus Here an overview of the properties and methods of the Search model If you find a bug or need a feature Create GitHub Issue"},{"title":"Table Select","href":"components/table/selecting.html","content":"Table Select tsdoxtabs Selecting the rows You can mark rows as selectable with the method of that name The callback fires whenever one or more rows changes state The arguments selected and unselected arguments are both arraysofrowindexes var table tsuigettable1 var popup tsuiNotification tablerows cells A D G selected true cells B E H cells C F I tableselectablefunction debugselected unselected popupsuccess JSONstringifyselected JSONstringifyunselected join var table tsuigettable1 var popup tsuiNotification tablerows cells A D G selected true cells B E H cells C F I tableselectablefunction debugselected unselected popupsuccess JSONstringifyselected JSONstringifyunselected join You can mark individual rows as unselectable with the selectable property var table tsuigettable5 var popup tsuiNotification tablerows cells A D G cells B E H selectable false cells C F I tableselectablefunction debugselected unselected popupsuccess JSONstringifyselected JSONstringifyunselected join var table tsuigettable5 var popup tsuiNotification tablerows cells A D G cells B E H selectable false cells C F I tableselectablefunction debugselected unselected popupsuccess JSONstringifyselected JSONstringifyunselected join You can control selection using the methods select unselect and toggle The methods take one or more indexes or an array of indexes as arguments var table tsuigettable3 tableselectablerows A E I B F J C G K D H L select0 1toggle2 3 var table tsuigettable3 tableselectablerows A E I B F J C G K D H L select0 1toggle2 3 You can also omit the argument to select unselect or toggle everything tsuigettable3toggle tsuigettable3toggle You can retrieve the selected indexes as an array with the selected method var table tsuigettable3 var array tableselected var popup tsuiNotification popupsuccessJSONstringifyarray var table tsuigettable3 var array tableselected var popup tsuiNotification popupsuccessJSONstringifyarray You can also confirm selection by passing one or more indexes or an array var table tsuigettable3 var popup tsuiNotification iftableselected0 1 2 3 popupsuccessAll selected else popupwarningYou must select them all var table tsuigettable3 var popup tsuiNotification iftableselected0 1 2 3 popupsuccessAll selected else popupwarningYou must select them all If you add columns to the table youll get a selection menu in the header var table tsuigettable2 tableselectable tablecolsOne Two Three tablerows cells A D G cells B E H cells C F I var table tsuigettable2 tableselectable tablecolsOne Two Three tablerows cells A D G cells B E H cells C F I The menu selects or deselects all visible rows If there are multiple pages in the table youll be presented with the opportunity to select all pages getJSONassetsrowdatajson functionjson var table tsuigettable4selectable tablecolsID Name Pricerowsjsonmax5 getJSONassetsrowdatajson functionjson var table tsuigettable4selectable tablecolsID Name Pricerowsjsonmax5 If you are loading the table data incrementally so you manage paging yourself you might like to know when all or none is selected via the menu The Table supports two additional callbacks that can be assigned via selectable tableselectableonselect onselectall onunselectall tableselectableonselect onselectall onunselectall You can also assign these methods directly tableonselect functionselected unselected tableonselectall function consolelogAll tableonunselectall function consolelogNone tableonselect functionselected unselected tableonselectall function consolelogAll tableonunselectall function consolelogNone Heres a summary of the methods that deal with row selection"},{"title":"Table Sort","href":"components/table/sorting.html","content":"Table Sort tsdoxtabs Sorting the columns You can make the Table sortable with a callback that triggers whenever a column is clicked We ship the Table with a builtin sort mechanism but youll still need to call it The sort method takes a column index and a direction tsuigetexample6 table tablecols Animal label Price type tsnumber rows Donkey 700 Baboon 1500 Coyote 250 Albatross 50 sortablefunctionindex ascending tablesortindex ascending tablesort0 true tsuigetexample6 table tablecols Animal label Price type tsnumber rows Donkey 700 Baboon 1500 Coyote 250 Albatross 50 sortablefunctionindex ascending tablesortindex ascending tablesort0 true The index is the column index and the ascending argument alternates whenever the same col is clicked twice If you manage your own sorting routine you can control the appearance of the column using selected and ascending tsuigetexample12 table tablecols label Example selected true ascending false setIntervalfunction var col tablecols0 ifcolselected colselected colascending colascending 1000 tsuigetexample12 table tablecols label Example selected true ascending false setIntervalfunction var col tablecols0 ifcolselected colselected colascending colascending 1000 Importantly note that the cell values must all be declared as numbers in order to sort numerically You can declare a hidden value while showing a human readable text using verbose syntax tablerows value 1 text One value 2 text Two value 3 text Three Custom sort Standard sorting only deals with numbers and strings If you need some kind of more advanced sorting for example if the value contains arrays or objects you can implement custom sort per column via the sort method tsuigetexample7 table tablecols label Fruit sort functionval1 val2 ascending sort random return Mathrandom 05 1 1 rowsBanana Apple Grape Pear sortablefunctionindex ascending tablesortindex ascending tsuigetexample7 table tablecols label Fruit sort functionval1 val2 ascending sort random return Mathrandom 05 1 1 rowsBanana Apple Grape Pear sortablefunctionindex ascending tablesortindex ascending "},{"title":"Table Sort","href":"components/table/status.html","content":"Table Sort tsdoxtabs Status messages We can show a message in the statusbar The message could be something like Showing 1020 out of 123 products or 23 products selected tsuigettable1 table tablestatusThis is the message tablerows 1 4 7 2 5 8 3 6 9 tsuigettable1 table tablestatusThis is the message tablerows 1 4 7 2 5 8 3 6 9 TODO Note about markdown in the status message"},{"title":"Table Styling","href":"components/table/styling.html","content":"Table Styling mytable tholdprice backgroundcolor rgb250 200 200 mytable tdoldprice backgroundcolor rgb255 225 225 mytable thnewprice backgroundcolor rgb200 250 200 mytable tdnewprice backgroundcolor rgb225 255 225 example2 tdpalered backgroundcolor rgb255 225 225 example2 tdpalegreen backgroundcolor rgb225 255 225 example2 tdpaleblue backgroundcolor rgb225 225 255 example3 tdveryspecial backgroundcolor rgb225 225 255 tsdoxtabs Styling the table The column type property works as a classname for both headers and cells tsuigetmytable table tablecols label Product label Regular Price type tsnumber oldprice label Sale price type tsnumber newprice tablerows Apple 130 100 Orange 075 050 Banana 200 125 tsuigetmytable table tablecols label Product label Regular Price type tsnumber oldprice label Sale price type tsnumber newprice tablerows Apple 130 100 Orange 075 050 Banana 200 125 This means that you can style the columns using CSS that looks like this mytable th oldprice background red newprice background green td oldprice background pink newprice background lime A similar property works for the rows if you switch to verbose syntax You will of course need to defined these classnames somewhere in your CSS file tsuigetexample2 table tablerows cells A D G type palered cells B E H type palegreen cells C F I type paleblue tsuigetexample2 table tablerows cells A D G type palered cells B E H type palegreen cells C F I type paleblue Finally the individual table cells can be styled with the type property Again you will have to switch to verbose syntax in order to declare this property tsuigetexample3 table tablerows cells text Normal text Normal text Special type veryspecial tsuigetexample3 table tablerows cells text Normal text Normal text Special type veryspecial "},{"title":"","href":"components/table/tabs.html","content":""},{"title":"","href":"components/tabs.html","content":""},{"title":"Time","href":"components/times/index.html","content":"Time Use the Time component to show a human readable time your app Assign datatsTime to a time to initialize it as a Time If you do not trust the users device time you can set the realtime attribute to mark the current time the moment when the page renders If you set an invalid datetime it will simply show the string If you find a bug or need a feature Create GitHub Issue"},{"title":"Local Time","href":"components/times/langs.html","content":"Time TODO This should go into a screenshot for the test suite edbmldeclareedbml14yR7I0asfunction edbml use strict var out edbmlout txt edbmlsafetext val edbmlsafeattr outhtml da deCH de enGB enUS en es fi fr hu id it ja ms nbNO nl no pl ptBR ptPT ro ru se svSE zhCN zhTWsplit forEachfunctioncode outhtml txtcode outhtml return outwrite If you find a bug or need a feature Create GitHub Issue"},{"title":"","href":"components/times/tabs.html","content":""},null,null,{"title":"UserImage","href":"components/userimages/index.html","content":"UserImage If the user didnt upload a photo the UserImage will generate a fallback image based on his or her name You can initialize a UserImage by assigning datatsUserImage to an img element A fallback image will be generated based on the users name if the image has no src attribute or if the image somehow failed to load You also can define initials in parentheses For exampleKarl Alfonso Benson KB you will get KB as an initials The image defaults to a size of 44x44 pixels If you prefer a different size youll need to specify both width and height as attributes in the HTML You can select users from a menu by adding the classname tsusermenu to a standard Menu while also replacing the icon i element with a UserImage Jim Bob Johnson jimbobcompanycom Karl Benson karlcompanycom Marshall Garrett marshallcompanycom Jim Bob Johnson jimbobcompanycom Karl Benson karlcompanycom Marshall Garrett marshallcompanycom Jim Bob Johnson jimbobcompanycom Karl Benson karlcompanycom Marshall Garrett marshallcompanycom If you find a bug or need a feature Create GitHub Issue"},null,null,null,null,null,null,null,null,null,{"title":"Buttons","href":"design/copy/buttons.html","content":"Buttons Button copy should be consistent and descriptive just like this subheader Buttons are crucial when it comes to copy for two reasons First they are one of the main ways in which users interact with the product Whenever a button is pressed something will happen Second buttons are among the most spacelimited elements in the UI which means that button copy needs to be extremely sharp With this in mind buttons on Tradeshift need to have two specific qualities they need to be collectively consistent and individually descriptive What does this mean Collectively consistent It is essential that the user can recognize buttons as such This is in large part made true through visual design theres a very limited and well defined set of possibilities for how buttons should look However this can also be strengthened by button copy being consistent in terms of how it relates to its context We achieve this through the following rules The button that begins the flow must work together with the one that ends it to make the flow a selfcontained unit All actions on Tradeshift that result in flows that require more than one step have two buttons that act as gates one to initialize the flow and one to finalize it The copy on these two buttons should be written with this in mind As a general rule if the opening button contains an action Reject document then the same verb should be present in the finalizing button On the other hand buttons that do not include an action for example Settings can have a more generic finalizer such as Done If a button results in the opening of a new page or a picker the title of said page or picker must be consistent with the name of the button So a button that reads Reject connection request should not lead to a picker that reads select value In very specific cases the title of the destination can read differently from the button but in 999 of cases they should read exactly the same Individually descriptive Whilst we want buttons to be consistent in how they relate to their context we also want them to be tailored to this context This means that as a general rule we do not want generic nondescript buttons that read proceed continue done or back Rather the copy on a button should be as descriptive as possible in terms of what the button will achieve of course within the length restraints implied Following the rule of thumb from the principle above if the button is related to an action then always use the verb in the button Furthermore if the verb is an action that can have multiple logical objects then include the object as well for example Reject can refer to documents connections and potentially more so describe what is being rejected If you find a bug or need a feature Create GitHub Issue"},{"title":"Copy in the Development Process","href":"design/copy/dev.html","content":"Copy in the Development Process When it comes to producing good copy embedding it into the development process is just as important as following the principles guidelines and rules If writing copy is not taken seriously as a task and allocated adequate time resources and interest the end result will not be good The following guidelines should help each product team to incorporate copywriting into the development process Copywriting is a skill and should ideally be done by the most capable Writing copy is a skill in and of itself and whilst it is related to a number of other skills it is definitely a skill that requires practice effort and knowledge Knowledge of the English language is a necessary but not sufficient skill and even skilled people will produce poor copy when rushed What this means is that each team should allocate copywriting to whoever is the most capable In some teams this might be the designer in others it might be the PM and in others it might be a developer What is important is that this is a conscious decision and not left to be picked up by a stressed PM on the day before release Good copy takes time effort and iterations Again no matter how amazing someone is at writing copy a truly good result can only be achieved through iteration and effort The first drafts for copy should be produced as early as possible in the development process and these should be discussed and iterated on much like everything else If you find a bug or need a feature Create GitHub Issue"},{"title":"Emails","href":"design/copy/emails.html","content":"Emails Emails are a crucial and highly complex aspect of the product Get it right When it comes to emails the complexity level is very high for 2 reasons There are many fields that must be filled with text sender subject headers body buttons explanations Emails are consumed in a context outside Tradeshifts control There are many different types of emails and things like tone etc will vary depending on the goal of the email Well now go through the different elements that comprise an email However before doing that two important questions must be asked Is this email necessary What is the goal of this email These questions may seem superfluous but it is important to be sure that only emails that are necessary and useful to the user are sent As such never take for granted that an email should exist At Tradeshift one requirement for an email being deemed necessary is that the email has a call to action for the user emails that do not encourage the user to take some action are not worth sending As such when answering the second question it is a good idea to keep the call to action in mind this will help in creating a good and cohesive email Once the purpose and call to action are determined we can proceed to the email itself As far as copy is concerned there are five sections that need to be created in an email sender subject title body and buttons Well go through these one at a time Sender This is a simple field where consistency rules There are two options for the sender When the email is a system email that is unrelated to any other user the sender should in most cases be Tradeshift When the email is related to an interaction between users the sender should be the user taking the action that results in an email via Tradeshift Subject Again the way the subject is written will very much depend on the nature of the email Nevertheless the subject is crucial since it plays the biggest role in determining whether the email will be read at all Having amazing copy inside the email is irrelevant if the email is never opened The most important thing to keep in mind is that emails revolve around the Call to Action CTA If an email does not have a relevant and important CTA then it is not worth sending There are two options for how the subject line should relate to the CTA when the action needed is critical for the continuation of a process and when it is not Note that this dichotomy is not necessarily the same as the action being important in a business sense an action can be very important businesswise but not be crucial per this definition For example a document being rejected in a small business context is a very important notification in a business sense but it is not critical in terms of being a bottleneck On the other hand a request for changes to a supplier registration form IS critical since the user will not be able to send invoices until the requested changes are made When the action is deemed critical the action should be frontloaded in the email by being the focus of the subject line So in the above example of a customer requesting changes on a suppliers registration form the subject line would read Your Supplier Registration form for customer requires some changes Other examples of subject lines for critical actions could be Action needed Register to Nike Supplier Network A document needs coding On the other hand when the action is not critical then the subject line should inform the user of the event that has occurred The call to action can then be introduced inside the email Subject lines for these types of email include the following user has sent you an invoice user accepted your connection request Your public profile is missing your logo Title The title section is quite a bit simpler as it is very much tied to the subject line The title should be very descriptive and summarize the purpose of the email for the user What this means is that the title can to a great extent mirror the subject line Following the examples above email titles could read as follows Subject Action needed Register to Nike Supplier Network Title As a supplier to Nike Inc you must complete the supplier registration on Tradeshift to be able to do business with Nike Subject user has sent you an invoice Title user has sent you an invoice on Tradeshift Body The copy in the body is where the majority of the information is conveyed This copy is also what leads the user to the button with the CTA so this section should provide the user with all of the information they might need to click on the button If the subject and title did not include the call to action you have received an invoice then it can be included here you have received an invoice from X Click the button below to see and accept or reject it If the call to action was included in the subject then this can be repeated along with an explanation of why the CTA is needed Buttons Currently Tradeshift emails typically contain a single button with the main CTA This button should be descriptive and tell the user exactly where in the product they will land In terms of functionality the button should take the user directly to the task needed they should not have to find their way once they click the button Thus an email informing the user of a new item on their To Do list should have a button leading the user to the item itself and not to the list as a whole As for the rest buttons on emails should follow the same guidelines as buttons in the rest of the product Read more in the buttons guidelines If you find a bug or need a feature Create GitHub Issue"},{"title":"Error Messages","href":"design/copy/errors.html","content":"Error Messages Error messages should be short and amazingly precise embodiments of the copy principles Error messages are extremely important yet they are the ones that are most often done carelessly or as an afterthought Error messages are what stands between a user continuing to be a user when something goes wrong and that user giving the program another chance Error messages are the copy that appears at the worst possible time Whatever it was that the user wanted to achieve was not achieved At best the outcome is irrelevant and at worst work time or worse may have been wasted As such error messages should do everything possible to convince the user to give the software another shot So what should an error message do 1 Be informative and concise Both of these are equally important Both extremes are problematic Too concise results in poor information transfer The most important thing is that the user knows what went wrong and what they should do next An error message that is too concise thus wont give enough information For example Something is broken This error message is certainly concise but it does not provide the user with any information besides the fact that their desired and expected outcome did not occur Conversely it can also be that an error message has too much information or information that is not easily decipherable An error message with too much information might read like The backup did not complete successfully An error ocurred The following information might help you resolve the error If an MM error is returned which is not defined in the standard FsRtl filter it is converted to one of the following errors which is guaranteed to be in the filter In this case information is lost however the filter correctly handles the exception 0xC00000EA Backup time 11292006 1157 AM Microsoft The important part is thus to provide enough information to give the user a clear indication of how to proceed but not so much that the user becomes more confused or simply gives up An error message with the right balance of concise and informative could be An error occurred while attempting to send your document Please try again If the issue persists please contact support 2 Keep in mind who is reading the error message Related with the point above You dont want to give the old lady information that would be interesting for the developer you want to give her the information she needs to solve her problem 3 Indicate the potential next steps Provide the user with the required steps they should take to either remedy the error or to arrive at the intended outcome It is important to always include the next step even when it is not something the user can solve themselves The following series of examples from Tradeshift show how we took a bad error message and iterated it into a good one At its earliest stage the error message looked like this CloudScan encountered an error while processing Document to Recipient This error message is not fantastic It makes it clear to the user which document caused the error and how the outcome differed from the intended but it does not provide the user with any information regarding what she should do next Thus we might change it to CloudScan encountered an error while processing Document to Recipient The most likely reason for this error is that the PDF file is corrupted Make sure that the PDF file can be opened in your PDF viewer This is better even though it is longer It provides the user with a clear action to take in order to solve the problem However it could still be improved As it is right now the most likely explanation is given But what happens if that is not the explanation The user might open the PDF in their reader just fine If this happens then they are in the same place as before without knowing what to do next Of course it can be that after this we do not have a next best explanation However its important to provide the user with a next action In this case we can add one more bit to our error message CloudScan encountered an error while processing Document to Recipient The most likely reason for this error is that the PDF file is corrupted Make sure that the PDF file can be opened in your PDF viewer If the issue persists please contact support It is important to give an action to the user even if we have no idea what is the correct way for the user to solve the issue In that case if the only solution is for the user to write support say that The user might do it by themselves but its better that were offering a solution than the user thinking they have to chase support around for a product that should be working in the first place By doing this we alleviate the pain that the user is experiencing due to the error For example this error message was shown when document delivery failed for an unknown reason Unable to send document Now it may very well be that we do not know why But a user faced with this problem is completely lost Nothing is gained by the brevity in this case Now if we add a few more words we can make the user feel a lot better even if we dont really have any more information than unknown error Due to an unknown error we were unable to send the document Please try sending it again If the issue persists please contact support We still dont know the cause of the error but two things happen here that didnt before First we are honest about not knowing this instead of looking lazy Second we encourage the user to ask us for help This shows that we care and provides a better user experience at the time where the user is at the lowest satisfaction point If you find a bug or need a feature Create GitHub Issue"},{"title":"UI Copy Principles","href":"design/copy/index.html","content":"Product copy principles Copy is an aspect of UI design that is often left by the wayside With a product that handles both sensitive and complicated processes it is essential that the design is supported by strong copy In the same way that the design decisions rest upon a set of principles copy decisions follow a similar pattern The following principles are meant to give very highlevel explanations for some of the decisions that we have made with regards to how copy should be and what it should do All of the other sections within these copy guidelines are informed by these principles Copy should above all else be informative and drive the experience forward Tradeshift is a complicated product for a complicated industry There is already a lot about the industry we work in that is very confusing so the copy should be as clear as possible This principle might seem obvious but it really is at the core of copy strategy This principle informs all the other ones in this list and every single line of copy on Tradeshift should aim to satisfy this principle Copy should be as concise as possible but clarity should not be sacrificed in favor of brevity Brevity is a good thing but not to the exclusion of everything else Following principle number one above brevity is only good insofar as it leads to informative copy Thus brevity is one extreme of an axis but not the goal An extremely short piece of copy can also be extremely uninformative an error occurred In such cases increased length is the preferred option in order to achieve maximum information transfer an unidentified error occurred during the uploading process Please try again If this problem persists please contact Tradeshift support In terms of tone copy should be friendly and casual but serious Were new young and exciting but were still dealing with peoples businesses money and other serious things This is a fine line to tread Tradeshift should not be boring and soulless but it still needs to be taken seriously A casual friendly tone is good You havent added a picture to your profile yet What are you waiting for Pop culture references These are not the droids youre looking for or even worse internetculture references are not Product copy should still feel natural when spoken out loud If a piece of copy doesnt feel natural in a context of one person explaining something to another then its not good enough Consistency is critical for a positive customer experience Product copy should be consistent across different parts of the product Marketing messages appearing within the product and emails generated by product activity should also be consistent with product copy to ensure understanding This consistency applies mostly to product names terminology key words and error messages but also applies to tone style punctuation format etc The page Terminology Cheat Sheet is the main resource to ensure consistency Product copy should assume as little previously existing knowledge as possible from the user In keeping with design principles Tradeshift users are very rarely expert users and in many cases the tasks they do at Tradeshift are not the principal tasks of their position As such product copy should not assume that the user possesses any deep technical industry or other specific knowledge If it sounds like an engineer talking to another engineer its not good enough If it sounds like an accountant talking to another its not good enough If it sounds like a lawyer talking to another lawyer or a lawyer talking to anyone its not good enough Copywriting is part of good design This means that copy is not something that gets added once a design has been finalized Rather copy is integral to the design process This means that placeholder copy is not good enough This does not mean that copy needs to be perfect from the very first wireframe What it does mean however is that copy cannot be Lorem Ipsum until an hour before deployment It is very much acceptable to write preliminary copy and to iterate on it as the whole design is iterated but copy is as important as layout in terms of providing a good user experience If you find a bug or need a feature Create GitHub Issue"},{"title":"Menu Pickers","href":"design/copy/pickers.html","content":"Menu Pickers With regards to copy there are three main sections in a picker The title the body and the buttons The layered lists we call Pickers are an essential aspect of how UIs are structured on Tradeshift Given that some of the most important choices on the platform are made through these copy on them is very important This is exacerbated by the fact that due to the layered structure a flow can become quite complex with layers being added and removed many times before the flow is over Thus it is essential for the copy in pickers to do two things 1 keep the user from getting lost and 2 push the action forward The title When it comes to the first objective of picker copy the title pulls most of the weight The title itself then has to do two things First it has to be able to tell the user exactly what needs to be done in this picker This means that somebody who looks at a picker without having just opened it should be able to know by reading the title what they were doing and what is expected of them Secondly the titles should give a sense of flow and continuity to the process Overall the user reading the title of a picker should know where they are and what is expected of them The first one is a matter of sharp and accurate description For example a picker whose body is a calendar could have as a title Choose A Date This would be a bad title since a user reading this without remembering how they got there would not know what the date is for A much better header for a picker with a calendar could be Set Due Date With this title the user knows that the date is the due date for an invoice and not the date of emission or any other date In a vacuum it might seem like a very small difference but all of these little things aggregate to make the product enjoyable and easy to use With regards to flow and continuity the best way to ensure this is to put together each title with the copy of whatever it was that triggered this picker Thus using the due date example above Clicking on Due in the create invoice page opens a picker named Due in and choosing specific date results in set a due date So when writing the title for a picker always look at it side by side with what triggered it The body The body is less straightforward because it can include very many different elements Broadly though they can be divided in two categories explanation copy and interactable elements The first type does not appear in all pickers only in cases where theres need for clarification regarding the purpose of the picker The guidelines for these are quite simple In these cases remember that clarity is king You will not be adding this type of copy unless its an already fairly complex flow so the only goal of this copy should be clarity Forget personality forget casual tone and focus on being clear The second broad category of copy in the body of pickers are the different types of value selectors themselves These can take the form of checkboxes radio buttons calendars free text boxes and more For these the same overall rules apply Clarity especially in labels but also the options themselves is the main priority The buttons Finally the last element that appears on pickers are buttons These buttons are no different than the buttons everywhere else in the product so the same guidelines should be followed Read more at the buttons guidelines If you find a bug or need a feature Create GitHub Issue"},{"title":"","href":"design/copy/tabs.html","content":""},{"title":"Terminology & Cheat Sheet","href":"design/copy/terms.html","content":"Terminology and Cheat Sheet The purpose of this section is to provide a condensed list of rules and terms for writing UI copy These are not specific or limited to certain parts of the product or elements in the UI but rather act as a set of broadly applicable rules In addition to this list of standard terms the rules that follow should help in writing good copy These rules are meant to be used by those planning on writing significant amounts of copy If youre interested in very specific aspects for example error messages you should look for those specific guides These rules will not miraculously help you write amazing copy if writing is just not for you though so if this is the case get someone else to help Remember that writing copy is very much a skill and knowing english is not enough Treat copywriting with respect and you will have a greater chance of coming up with something great Leave it until the last minute or as an afterthought and the end result will reflect this Do use Do not use Reason Connection Contact We focus on action and relationships Connection is action oriented while contact is static Recipient Receiver A receiver refers to a machine while a recipient is the correct term when talking about people invoice Invoice Do not capitalize words in the middle of a sentence wants to connect with you wants to join your network joining a network is ambiguous The action is to connect and networks are then formed organically Connection request Network request We focus on the action which is the connection network is ambiguous Document status Document state Status is generally understood in business state is tech jargon StatusVoid StatusVoided Voided is only the past tense of the verb to void and never an adjective Supplier Vendor Both are fine we have chosen supplier as a matter of consistency Validate Transcribe Transcribing connotes a time consuming and arduous task At Tradeshift we use clever technology to do these things so there is no need to transcribe only review and validate Validator Reviewer see above Processing in queue Processing indicates motion and progress whilst in queue signifies lack thereof Always attempt to include subject verb and articles in a sentence This is so that copy does not sound like a robot Sentences like Error importing file are technically correct but do not convey meaning well Being technically correct is not enough copy needs to read as a person explaining something to another Never sacrifice clarity in order to sound casual Copy should be whenever possible casual natural and friendly but clarity remains the top priority Be specific and precise with your word choice Search isnt the same as filter send might not be the same as submit and cancel is not the same as go back Particularly in actionoriented copy make absolutely sure that what you say is what you mean to say Avoid overusing jargon and be very wary of abbreviations Following design principles Tradeshift is a product with a very wide user base and is not expected to be a primary working tool As such copy should aim to inform users with a very wide variety in knowledge Of course sometimes it is impossible to avoid jargon but consider it carefully Abbreviations on the other hand are almost never OK Site should be Website Info should be Information and Invite should be Invitation Dont fall for the people dont read trap This has been repeated as a mantra for a very long time but UX experts across the board agree that this is not true Specially when it comes to headers and buttons users read Do not allow copy to be steered by this assumption Avoid using passive voice Passive voice invoice was sent by you creates awkward sentences where the subject is deemphasized Unless the intention is specifically to do this do NOT use passive voice Do not leave copywriting to the last minute Writing copy is a task like any other and requires time thought and effort to come up with a good result If you leave it until the last minute it is going to be bad If you write the first thing that comes to mind and call it a day it is going to be bad So instead of filling a design with Lorem Ipsum start working on the copy as an integral part of the design and iterate on it like you would anything else If you find a bug or need a feature Create GitHub Issue"},{"title":"Design Principles","href":"design/index.html","content":"Design principles By taking the following eight principles into account when building a Tradeshift application youll maximize your chances of creating a good user experience For most people Tradeshift is not their primary work tool It means that these people will only use Tradeshift occasionally Hence we generally dont consider the user an expert user and the core parts of Tradeshift have been designed with this in mind This doesnt mean we cannot or shouldnt provide powerful interfaces that cater to experienced users though By adapting the interface through a users repeated use and providing powerful shortcuts expert users will be able to experience a productivity boost 1 Remember users choices Users often need to repeat their work tasks Make sure to remember the users previous choices and inputs to support future choices If at all possible automate the mundane tasks Adjust defaults with used values Provide access to previously used values Whenever applicable ask the user if the used values should be new defaults When a user starts using Tradeshift the list of currency options contains one suggested currency the one used in the company registration country If the user uses another currency this newly used currency will appear as an option the next time the user needs to fill out the currency value This way lists of regularly used values are created Opposite principle Always providing the same ground zero to users no matter when or how many times the user has used your application Simultaneously clearing previously used values This may be relevant in other types of applications where values are never reused or where different users share one account 2 Build learning into the UI Consistent use of the design patterns provided in this guide is important to support the users learning and recognition Reuse and consistent use will give the user the ability to apply knowledge from one functional area to another lowering the cognitive load and increasing performance So do only invent new design patterns when absolutely necessary Reuse design patterns to provide an experience of recognition Be mindful of the users first run experience Learning to work with dynamic option lists in the context of selecting a unit type here aided by a first run embedded description creates knowledge about how to solve other tasks The currency selector uses the same design pattern as the unit type selector The user can now leverage previous experience since the designs are based on the same pattern Opposite principle Individual applications on mobile phones especially games are often wildly different to establish individual identity and to better optimize to very narrow tasks supported by that specific app But since allmost Tradeshift apps are extensions all related to the core consistency is chosen 3 Keep users in task solution mode People come to Tradeshift to work with their business data and flows not to work with buttons inputs or manuals Keeping the users in the functional flows is important Avoid forcing the user to outofcontext settings pages to change things that could be adjusted incontext Provide sensible defaults that potentially prevent the user from wanting to change a setting in the first place Further avoid forcing the user to read FAQs and manuals out of context Be mindful of the users first run experience Whenever a user intends to export Tradeshift data make sure you know why If you can provide a view of the data or functionality thatd keep the user in the flow the user gets a better experience and your product is better Avoid settings pages Keep help descriptions in the app not outside Understand why and when the users want to export application data Consider if an improvement could solve the need Example Letting the user update address and company registration information from the public profile page makes settings pages for these details unnecessary Opposite principleEncouraging the user to spend significant time understanding your app properly before using it Eg by letting the user read a manual and a separate getting started guide Then still before use configuring the product for correct use Many medicalhealthcare products work this way as improper understanding can be dangerous Quickbooks is an example of a settings heavy application as well but it seems Intuit is moving away from this approach as it clearly Tradeshifts internal tests show makes initial use harder 4 Mobile first Global reach includes users who are not primarily working in front of a computer all day Its users whore working on the road and even users who dont ever have access to a laptopdesktop computer Most often its valuable thinking the mobile use cases first itll improve the experience for all other users Given the diversity of the markets Tradeshift is made available in and the shift towards mobile in more mature markets dont underestimate the mobile scenarios Consider the mobile use cases first Be optimistic when considering the mobile use cases Be aware that many Tradeshift users will have both a regular computer and a mobile device Some will not have a computer ExampleMany users check their email continuously on their smartphone A primary vehicle for notifying users and getting users to complete tasks in Tradeshift rely on email as communication channel such as when a new invoice is received Allowing smooth transition from an email notification telling about the received invoice to actually accepting or rejecting the invoice on the same device allows the user to react faster Also the user doesnt need to mark the email as unread or otherwise flag it to see it on a desktop computer later Opposite principleExpert systems where users are expected to work on a computer in a known locationsetting and where the user is not pulled into the application via eg email notifications While we do have this kind of applications on the platform the majority of future features integrate tightly into email and the ability to respond from these 5 Help the user focus Establish a visual hierarchy on you application pages that support the prioritized features the page is intended to present Most used features get dominant colors positions and sizes while less used features are visually downprioritized The design patterns are created to guide you to doing this Make sure to only present the data the user needs to make decisions at any given time Avoid just rendering out all the data you have just because you have it Render out only the data necessary for your use cases Establish a clear visual hierarchy optimized for the use cases you intend to solve The prioritization you do when designing your app is cognitive load you lift off the end users shoulders Opposite principle Specialistexpert systems used daily by users can typically present more data information and actions than nonexpert occasionally used systems The expert user has plenty time to master complex interfaces and will eventually receive intensive product training So in those cases intricate shortcuts and an abundance of information in large tables can be empowering Many Tradeshift users though are often occasional users whose primary profession is normally not within the functional areas covered by Tradeshift eginvoice creator enterprise invoice coder 6 Provide a sense of context Whenever the user navigates your application make sure to provide enough visual clues that the user understands where and why he arrived at a certain screen Buttons with explanatory text is one solution Animations to explain the scene changes is another solution Stacking pickers is an example of this The visual stacking provides a trail back while each layer appears in a way that supports the same concept Think beforeafter states into any action Use clues such as animation to show how one item relates to another Opposite principle Expert systems again or alternatively text based systems such as DOS prompt or Terminal Here the visual clues have been almost completely omitted and rely on the user to contain and know context 7 If it looks easy its easier to get started Tradeshift encourages use by having an interface that looks easy to use Instruments such as slightly oversized elements and typography plenty of whitespace clear colors simple iconography must all be considered when laying out your application Avoid things like overcrowding areas unnecessary divider lines stacking content closely microtypography and unaligned elements Use a visualUI designer if in doubt Spend time ensuring your application screens are well laid out and correspond with Tradeshifts UI guidelines Reevaluate all elements presented in your application UI and consider if they need to be there to let the user make decisions and actions Use a UI designer to get the visuals right if in doubt Opposite principle Heavier applications such as 3D software or even games can allow a steeper learning curve as users both need all functionality at their fingertips all the time much less linear flow of actions and time and interest in feature discovery isnt unexpected 8 Do enduser testing No heuristics in the world can replace enduser testing Get to know the truth about the target users ability to interact with your app Improve when necessary Opposite principle When building internal tools where the users are within arms reach The benefits of having direct access to every user can eliminate the need for classical enduser testing as the product in use is the actual testing If you find a bug or need a feature Create GitHub Issue"},null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,{"title":"Buttons","href":"design/patterns/buttons.html","content":"Buttons A collection of button styles exist to visually prioritize the possible actions in your application Styles include the color size and position of the buttons Applying these button styles correctly will help the user focus on the most likely next action By prioritizing the user flows in your application you will know which flows are most likely to be used by the majority of users One way of making these most likely paths clear to the users is by applying the appropriate button styles Four main button styles exist Primary button The most likely action the user will take On desktop and tablet size interface this button is almost always positioned in the top right corner of the window or its attached at the end of the content in the main content area Secondary buttons Functionality that many users will need but without which the application pages would still work The secondary buttons are located to the left of the primary button on desktop and tablet size interface Tertiary buttons Functionality that isnt often used by the majority of users should be styled and positioned as tertiary buttons Example exporting or deleting a viewed document Kill button Functionality that performs a deletion or rejection action These buttons are visually styled to alert the user and are most often placed in pickers to confirm an action Example confirming the deletion of a document Its worth spending some time reviewing functionality such as invoice creation and viewing in Tradeshift to see these principles in action Above is the invoice creation screen The Send button is primary for this functionality Preview is secondary and Discard is tertiary A number of other tertiary actions are grouped within the tripledot icon These are actions such as importing document contents from a file sending a test email with the document attached etc Above is a Kill button which confirms the action of deleting a document Its styled to indicate the destructive nature of its action If you find a bug or need a feature Create GitHub Issue"},{"title":"Emails","href":"design/patterns/emails.html","content":"Emails Points to keep in mind Have exactly one message in your email Be concise and to the point of why did the user receive this email what reaction is expected from the user and which other party triggered the email to be sent Present the most expected action as a primary action button just below the introductory text Dont advertise All promotion is managed by Tradeshift and sent out through optin newsletters Application emails are for actionsappevents only Irrelevant content dilute the signalstrength from other Tradeshift emails Make your emails work on mobile devices If you find a bug or need a feature Create GitHub Issue"},{"title":"Full page apps","href":"design/patterns/fullpage.html","content":"Full page apps Apps may run with the Tradeshift navigation interface the chrome visually hidden while still technically running inside the Tradeshift chrome and showing the Tradeshift URL in the address bar The Supplier Registration app takes over the full viewport while running on Tradeshift Under normal conditions any app should rarely have the need to take over the full viewport The approach is also only recommended for flows where new users need to perform certain actions before using Tradeshift Expect users who are used to using Tradeshift to want to have access to the global navigation If you find a bug or need a feature Create GitHub Issue"},{"title":"Structure","href":"design/patterns/index.html","content":"UI Structure Due to the responsive nature of Tradeshift you should pay careful attention to how UI elements transform across screen sizes The applications navigation elements transform as illustrated in the following Small phone size devices 1270px The Global Menu is expanded and the TopBar behaves as in tablet style Global Menu The Global Menu is the primary way for the user to switch between the main functional areas Core applications such as Document Creation and User Settings provide a Global Menu Item for the user to access these applications directly The Global Menu is present in all contexts and cannot be disabled It will however expand and collapse based on available screen space TopBar The TopBar serves multiple purposes and takes on different appearances In the examples above the TopBar contains buttons for actions but other uses of the TopBar such as tabbed navigation are possible Main Main is where most task solving takes place Tradeshift applications are designed on a fluid grid which lets applications fluidly fill out the entire main content area on all screen resolutions up to 1270 point width Attempts should always be made to fill out the main content area and if this is not possible you should visually define the boundaries of the functionality If you find a bug or need a feature Create GitHub Issue"},{"title":"Navigation Items","href":"design/patterns/nav.html","content":"Navigation Items Menu items can be inserted in the Global Menu to provide direct access to your app An application icon must be provided as well as a name for your application A highlight color can be specified for your menu item allowing integration of your visual identity in combination with your custom icon Shortcuts are only available in tablet size and are stacked vertically along the left side of the screen under the Tradeshift logo mark The shortcuts are basically global menu items that have been defined to also appear in the shortcut list This means that the shortcuts are a subset of the global menu items Only specify your global menu item as a shortcut if frequent and repeated access to your functionality on mobile devices is necessary TopBar The Topbar can be customized in a few different ways Buttons for the TopBar When using the TopBar to present buttons the actions assoicated to the buttons are expected to manipulate the entirety of page contents they are top level actions The buttons are also contextual and can change with application state The invoice creation example has document delete save and send as contextual actions These actions modify the entirety of whats on the page More finegrained controls such as adding lines belong to the contents of the document and should never appear in the contextual bar as actions An alternative example connector app and connections page is when the page contains a collection of objects In this case the contextual action of adding another object to the collection is allowed as contextual action as it alters the collection being the highest level on that kind of page Tabbed navigation The TopBar can also contain tabs with the purpose of splitting related contents into subsections that can be processed individually in any given order An example is this documentation Progresstabbed navigation When a tabbed navigation is preferred but theres a requirement for users to process all tabs in order the progresstabbed TopBar is used Note that the progresstabbed navigation leaves ample space for a flow headline by keeping the progress tabs below the TopBar space Progresstabbed navigation works well for setup flows where all steps are required such as a custom registration flow Filtering and searching For managing complex lists the TopBar can be completely exchanged with search and filter functionality This is especially usable for long lists such as the documents list pages If you find a bug or need a feature Create GitHub Issue"},{"title":"Option Lists and Pickers","href":"design/patterns/pickers.html","content":"Option lists and pickers In most cases Tradeshifts user interface doesnt rely on the standard select element for option selection Instead options are presented in layered lists This is what we call Pickers Structurally the Pickers allow the presentation of more complex selection scenarios than the select element allows In the concept illustration below selecting an invoice due date requires either a relative or an absolute value This can be combined in one seamless flow using Pickers Pickers have been designed to work similarly across different devices and screen sizes as a picker panel basically is a collection of form elements styled to meet phone styling requirements For huge lists with hundreds or thousands of options a search element can be enabled In the following example the list of options contains a few hundred unit types Only the previously used ones are shown Access to the full list is provided by free text search Searching for units in a picker Copy Guidelines Writing copy for pickers for the most part consists of writing copy for a bunch of individual elements that can be found elsewhere in the product There are essentially three distinct groups of copy when it comes to pickers Title The title should be as descriptive as possible regarding what the goal of the user is Furthermore the title should match the copy of the element that triggered the opening of the picker Body The body can include two different elements clarificationexplanation copy and value selectors The selectors should follow the same guidelines as throughout the rest of the product The clarificationexplanation copy should be as clear as possible No personality no humor this is strictly a help text in a complex flow and its only goal is to clarify the actions expected of the user Buttons Some pickers will include buttons When they do these follow the rules of buttons in the rest of the product Read more about buttons including copy here or read the indepth section on button copy Ways of presenting options Pickers are used whenever you need a field value populated from existing data Ie if the user clicks an input element and a value is returned to a field on the existing page a picker should most often be used Here are the standard option Single value selection Multiple value selection Advanced value selection Drilldown with nested values in a hierarchy of pickers tree structure Option manipulation Add option Modify option Remove option part of edit Navigation options Object navigation hub click invoice in documents list and get options in picker Advancedcustom use Invoice line transformation across devices Simple options Checkboxes multi select or single value boolean or radio buttons single select can be used when the following is true Less than 5 options in list Options cannot be manipulated The standard select elementdropdown is never used In cases that is needed always use a picker as this provides a more consistent user experience for value selection If you find a bug or need a feature Create GitHub Issue"},{"title":"Switches","href":"design/patterns/switches.html","content":"Switches Switches also referred to as toggles in regular UI design lingo are used for enablingdisabling options In most cases a switch should be used instead of a standalone checkbox Dont use switches when When a single confirmationcheck is required to progress to next step eg signing or confirming Here a checkbox should be used as both enabled and disabled state in a switch should be allowed values in any context If you find a bug or need a feature Create GitHub Issue"},{"title":"Tables","href":"design/patterns/tables.html","content":"Tables The core table designs in Tradeshift aim to be similar to best practices and existing standards Due to the responsive nature of Tradeshift UI some extra considerations should be made to ensure that the user can access and understand the information contained For tables the following concepts should be considered Linewrapping When enabled text inside table cells will break to multiple lines if theres not enough horisontal space Disabling linewrapping makes every row same height as text inside cells is only one line Proper handling of relative cellwidths and overflow is important when lines are not allowed to wrap Rowselection When enabled each line has a checkbox in the first left column This column is fixed so if the table scrolls horisontally the selector first column stays in place This allows the user to make selections while browsing all columns Clickable rows In many cases table rows represent single objects and are clickable This is symbolised by having a last column containing three dots Responsive column handling To better adapt to the available screen space mainly width careful consideration of textoverflow and hidingshowing columns should be done In cases where an entire row is clickable and links to an object columns can often be left out in smalldevice table views as the contents of these columns will be visible on the object anyway When linewrapping is disabled text in cells stay on one line keeping rows same height Enabling rowselection provides a checkbox in the first column that is fixed on a scrolling table Linewrapping disabled rowselection enabled Here linewrapping is enabled so text in cells flows into multiple lines Rowselection is disabled so theres no checkbox per row Linewrapping enabled rowselection disabled Table Linewrapping disabled rowselection disabled Linewrapping enabled rowselection enabled Row selection The video below visualises how bulk actions light blue bar appear when rows are selected The bulk actions are only possible when rowselection is enabled Small device considerations For smaller screens its worth deciding which columns to hide if any Aim at scrolling in only one direction vertical whenever possible In the example below the lines are clickable and all details can be provided in the object view instead of trying to get everything into the table If you find a bug or need a feature Create GitHub Issue"},{"title":"","href":"design/patterns/tabs.html","content":""},null,{"title":"Root Panels","href":"development/rootpanels/index.html","content":"Root Panels Root panels Root panels is a work in progress This is a developer preview The API markup or layout of this component might change significantly We can position Panel elements as direct children of the body to autogenerate labeled tabs in the ToolBar This will allow multiple Main to exist If the developers wants to reflect the selected tab in the URL for history support he must add some custom functionality to the onselect method of each individual Tab in the TopBar But this should be made easier see note below We should implement onselect as a configurable method on the TopBar API so that this becomes easier to setup The method couldpass the selected Tab andor selected index as an argument Panel Two A In this Panel the nested Main contains two additional Panel elements to autogenerate a TabBar the TabBar is shown at the top of the page Panel One Panel Three Panel Two B Chuck cow Tradeshift pork shoulder loin drumstick swine biltong pastrami fatback meatball ham rump boudin picanha Ground round beef ribs doner boudin brisket biltong tbone capicola Corned beef flank pancetta sirloin jowl meatball pork chop alcatra Landjaeger biltong pork chop alcatra spare ribs turducken strip steak bresaola shankle chicken pastrami doner salami brisket Ham hock biltong tbone salami sausage pork spare ribs beef flank pig Kevin meatloaf turducken short loin sausage spare ribs tongue ham hock leberkas ham strip steak pig jerky Tenderloin alcatra leberkas shoulder sirloin pancetta short ribs pastrami tbone tritip pork belly kevin Tenderloin filet mignon chicken spare ribs meatball capicola ham jerky swine bresaola pork chop ribeye cupim tbone bacon Pork belly tail swine ham hock alcatra pork chop shoulder pastrami spare ribs venison hamburger beef drumstick pancetta Kevin swine ham spare ribs strip steak andouille rump Pork chop rump filet mignon shankle pastrami ground round landjaeger ribeye shoulder strip steak chicken bresaola Swine turkey bresaola flank jerky salami bacon filet mignon Turducken jowl pork chop meatball pastrami swine ball tip leberkas Doner cow chicken rump swine flank salami Pork belly bacon tenderloin tongue cow tritip alcatra short ribs turducken chicken biltong drumstick meatball Drumstick frankfurter shank sausage andouille shankle Strip steak flank brisket ham pastrami shoulder hamburger chicken drumstick meatball tail Brisket drumstick meatball leberkas beef ribs Prosciutto bacon pork shoulder salami Meatloaf salami beef chuck biltong Flank sausage shoulder bresaola sirloin prosciutto boudin cupim strip steak andouille pancetta Landjaeger drumstick spare ribs salami venison picanha pork rump cupim andouille sirloin beef ribeye meatloaf Bacon short loin pork leberkas shank salami rump pig ribeye porchetta tail spare ribs Turducken short ribs prosciutto venison fatback sirloin beef strip steak rump shankle ground round Tenderloin picanha landjaeger beef ribs Drumstick ribeye prosciutto salami Tenderloin bacon spare ribs rump kielbasa Strip steak tongue bacon andouille meatloaf beef ribeye salami brisket pancetta short loin short ribs rump turducken Andouille turducken meatball prosciutto corned beef tbone Jerky shoulder andouille kielbasa tbone leberkas pork chop Turducken hamburger prosciutto ground round pork chop frankfurter jerky Tenderloin pastrami picanha doner short ribs ham hock short loin ground round shankle ham kevin capicola turkey brisket Jowl ribeye rump short ribs bacon ham tenderloin doner hamburger tbone sausage cupim turkey shankle short loin Bacon ipsum dolor amet boudin beef ribs landjaeger sausage pig turkey short loin pork loin ball tip chuck kevin doner shank flank Tradeshift kielbasa strip steak andouille chicken corned beef alcatra tritip sirloin pancetta brisket pork loin drumstick landjaeger ham hock Pork ball tip picanha drumstick jerky ham hock Venison meatloaf strip steak pork beef Pork chop sirloin ball tip spare ribs short loin porchetta capicola fatback leberkas drumstick turducken frankfurter Bacon ribeye turducken landjaeger corned beef capicola ground round Meatball pork chop spare ribs sirloin leberkas swine tritip ham hock pork loin brisket Filet mignon beef corned beef jerky pig alcatra ground round kielbasa Ham tenderloin beef jowl prosciutto Alcatra cow meatball beef ribs shoulder venison Tenderloin beef ribs jowl bresaola ball tip Ribeye pastrami venison porchetta chicken drumstick meatloaf boudin Beef ribs cow biltong salami meatball shankle fatback ribeye sirloin meatloaf strip steak turkey capicola bresaola cupim Rump corned beef alcatra cow salami shankle boudin brisket sausage ham hock landjaeger tbone picanha sirloin Prosciutto ham picanha chicken ham hock Alcatra sirloin beef tbone rump Jerky pork chop picanha andouille Rump boudin ham frankfurter tbone leberkas Tbone hamburger sirloin andouille tenderloin prosciutto tongue cupim shoulder meatloaf Ribeye filet mignon tbone short ribs jerky Strip steak pork loin spare ribs flank bacon sausage cow shank short ribs fatback Cupim chuck brisket beef ribs pork loin alcatra drumstick Pastrami meatball biltong alcatra fatback boudin short ribs drumstick chuck jerky turducken hamburger Venison cow sausage rump picanha turducken meatloaf shoulder strip steak jowl Chicken porchetta doner sirloin pig shank flank bacon rump corned beef Pastrami tenderloin jowl tbone doner drumstick pork chop shankle leberkas meatloaf ham hock pig Jerky ground round rump biltong tritip swine cupim corned beef picanha Cow chicken sausage tritip Jowl pastrami tail short ribs bresaola flank meatball tbone boudin sausage shoulder fatback andouille Frankfurter tail pancetta tritip pork meatball ham hock swine filet mignon andouille hamburger Sirloin alcatra picanha pastrami chuck ham jerky kielbasa tail boudin corned beef spare ribs brisket Drumstick fatback strip steak bacon brisket kevin pork ribeye hamburger Rump beef jowl drumstick ground round fatback salami frankfurter porchetta pig pork belly swine flank Pork loin corned beef shoulder landjaeger ham hock picanha ball tip Picanha pig cow landjaeger pastrami chuck tail Bresaola boudin frankfurter strip steak tbone pork belly shoulder brisket Ham jerky tenderloin short loin Spare ribs drumstick short loin pork loin Ham hock capicola jowl venison porchetta cupim spare ribs kevin tritip corned beef turkey tongue sirloin Boudin short loin alcatra frankfurter fatback spare ribs andouille tritip chicken capicola Chicken tongue jowl ground round corned beef alcatra ball tip meatloaf turducken jerky venison shank salami Cow beef cupim pork chop doner biltong kielbasa picanha ham tbone ball tip Jowl frankfurter ground round short ribs kevin leberkas sirloin shoulder pork loin boudin spare ribs picanha brisket pig beef Pork chop shank jerky cow pancetta short loin tail fatback pork belly tongue kevin Ground round pork chop beef short ribs ball tip cupim sirloin ham alcatra kevin Ball tip short ribs picanha alcatra kevin spare ribs rump shank ham Shankle pig shank turducken Turkey landjaeger ground round biltong Biltong rump frankfurter bacon chicken alcatra ham ribeye tongue Tongue filet mignon pig pork chop andouille shoulder tenderloin picanha sausage jowl brisket meatloaf Pastrami tongue swine bresaola picanha leberkas meatball chicken jerky tenderloin doner tbone pork chop Strip steak beef ribs venison porchetta sausage meatloaf hamburger Bacon spare ribs sausage porchetta prosciutto cupim meatloaf corned beef Andouille shankle tenderloin venison frankfurter rump cow ball tip pancetta hamburger Brisket alcatra bresaola doner flank shank Prosciutto salami venison frankfurter pastrami Porchetta jerky swine ham hock tritip shoulder pork loin turducken jowl Panel Three In this Panel we test that the SideBar is also working Panel One Panel Two "},{"title":"Get Started","href":"getstarted/index.html","content":"Get started This is a good starting point also for visual designers who prefer to work in HTML because the script will inject the stylesheet along with the fonts and icons etc edbmldeclareedbmlZ2dVzsb1asfunction edbml use strict var out edbmlout txt edbmlsafetext outhtml To get Tradeshift UI up and running on your page simply include tsjs in an appropriate version The latest version is txttsuiversion return outwrite UI components are initialized on the DOMContentLoaded event but this might change some day To make sure that all the components are initialized before you do something to them you can wrap you code in a callback like this tsuireadyfunction var component tsuigetelement componentdosomething Before DOMContentLoaded the callback will be executed later After DOMContentLoaded the callback will execute immedeately You can perhaps make it easier for yourself by kickstarting your app with a tsuiready callback because then you wontt have to worry about it later on tsuireadyfunction boostrapeverything Before we begin youll need to mark up your page with the basic layout If you find a bug or need a feature Create GitHub Issue"},{"title":"Layout","href":"getstarted/layout/index.html","content":"Layout This is the minimum viable HTML boilerplate for UI components to work out You may want to tweak the viewport meta tag but this is a good starting point Layout Main content TopBar The page should have a TopBar even if you dont plan to use it Thats because the topbar is always visible in mobile layout where it functions to toggle the main navigation menu Main The Main draws the scrollbar now that body overflow is hidden This setup will let us use absolute position to emulate fixed position which doesnt work right inside iframes on mobile devices MainContent The MainContent element should contain more or less everything your app has to show Asides If youre using Asides its important to place them outside Main like this Main content Aside content With this in mind you are ready to start using components If you find a bug or need a feature Create GitHub Issue"},{"title":"Basic rules","href":"getstarted/rules/index.html","content":"Basic rules UI components would like to assume ownership of The datats HTML attribute All HTML attributes that start with datats dot All HTML attributes that start with datats dash All CSS classnames that start with ts dash The global namespace object tsui Rule number one is to not use ts prefixed CSS classnames in your app UX designers can continue reading the Design Principles while developers may skip directly to the UI Components section If you are new to Tradeshift you should probably read both If you find a bug or need a feature Create GitHub Issue"},{"title":"Usage","href":"getstarted/usage/index.html","content":"Basic usage You will use any combination of HTML attributes CSS classnames and JavaScript interfaces to deal with the different components Most components are used simply by adding the datats attribute to elements The framework will recognize this attribute and add behavior and styling Config attributes Additional attributes may be used to configure the component By convention these will be prefixed with datats including the dot The datatsopen attribute would for example open the aside JS interface The component may also expose a JavaScript API For example the Aside can be opened with a method call instead of an attribute You can get hold of the implementation using tsuiget which takes an element as argument var myelement documentquerySelectormyaside var component tsuigetmyelement consolelogcomponent object tsuiAsideSpirit componentopen APIonly components Components that embody more complex behavior will usually be dealt with through a pure JavaScript API so without writing markup This will come in handy when we decide to change the complex behavior at a later stage tsuiDatePicker title Your Birthday value 19730326 open When making apps with UI components theres a few basic rules we would like you to observe If you find a bug or need a feature Create GitHub Issue"},{"title":"Tradeshift UI","href":"index.html","content":"Tradeshift UI includes menuhtml svgicons menujson If you find a bug or need a feature Create GitHub Issue"},{"title":"Tradeshift UI","href":"intro/index.html","content":"Tradeshift UI Tradeshift UI UI components range from simple buttons and icons to fancy datepickers and dropdown menus The target audience for Tradeshift UI is both developers and designers For Developers For Tradeshift apps the UI components are built to allow for consistent styling and experiences across internal apps For thirdparties the UI components are designed to bring visual consistency with internal applications as part of the Tradeshift platform Get Started Everything you need to use Tradeshift UI Components in your app Components Overview The building blocks that Tradeshift apps are made of Great Appendix Colors typography bonus features and notes on responsive design For Designers For our designers the UI components are designed to allow rapid prototyping without duplicating efforts between prototypes As a result of being standardized they will also act as a single point in Tradeshift for designers to revise UI components Design Guidelines The foundational principles and concepts of the Tradeshift UX Design Patterns Recurring solutions to challenges youll encounter when designing a Tradeshift app UI Copy Strong copy is essential we give you this guide to help you have great copy with your great designs"},null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,{"title":"Search","href":"search/index.html","content":"If you find a bug or need a feature Create GitHub Issue"},null] \ No newline at end of file diff --git a/docs/src/xhtml/TEST.xhtml b/docs/src/xhtml/TEST.xhtml new file mode 100644 index 000000000..d8213c73c --- /dev/null +++ b/docs/src/xhtml/TEST.xhtml @@ -0,0 +1,17 @@ + + + + Testing + + + + + + \ No newline at end of file diff --git a/src/spiritual/spiritual-gui/gui@wunderbyte.com/concepts/gui.Document.js b/src/spiritual/spiritual-gui/gui@wunderbyte.com/concepts/gui.Document.js index 45e759b29..ea271da35 100644 --- a/src/spiritual/spiritual-gui/gui@wunderbyte.com/concepts/gui.Document.js +++ b/src/spiritual/spiritual-gui/gui@wunderbyte.com/concepts/gui.Document.js @@ -52,15 +52,33 @@ gui.Document = (function() { target.addEventListener(type, that, capture); }); }; - add(document, 'DOMContentLoaded visibilitychange'); + add(document, 'visibilitychange'); add(document, 'click mousedown mouseup', true); - add(window, 'load hashchange resize'); + add(window, 'hashchange resize'); if (!gui.hosted) { add(window, 'orientationchange'); } if (!(window.chrome && chrome.app && chrome.runtime)) { add(window, 'unload'); } + /* + * Setup to support async loading (via `script.defer` or similar) + */ + if (document.readyState === 'loading') { + add(document, 'DOMContentLoaded'); + add(window, 'load'); + } else { + setImmediate( + function parseTheRestOfTheScript() { + this._ondom(); + if (document.readyState === 'interactive') { + add(window, 'load'); + } else { + this._onload(); + } + }.bind(this) + ); + } }, /**