Swagger-ui: How to modify v3.0.3?

Created on 28 Mar 2017  路  14Comments  路  Source: swagger-api/swagger-ui

Hi. I'm liking the new update to v3. It will be nice to have everything looking the same.

My question is regarding changing the look and feel. How can I, for example, remove the green swagger navbar when I integrate swagger-ui into my site? Is there documentation for this somewhere and I just haven't found it yet?

I used to just change the swagger-ui.js, but it looks like now you're using react. Anyway, I haven't figured out where this lives yet.

Also, I'm assuming that the right way to integrate this into my angular based site is to copy the contents of the dist folder over. I've got it working doing that, but had to remove swagger-ui.js I'm not sure if I got lucky doing that, or if that's not the right way and that file needs to be there.

Thanks for your help!

support

Most helpful comment

Hi Jay!

re: the dist folder, we have four files in dist now, which are explained in the release notes for v3.0.0, under the "Distribution files & usage" section.

You were correct! You don't need swagger-ui.js, the other three will provide everything you need.

As for customizing the look and feel, you'll want to customize the layout in /src/standalone/layout.jsx for that. That requires a full dev environment... we're working on documentation around this, but if you need guidance please reply and I'll help out.

If you want to hide the Swagger bar and be on your way, you can override the Topbar component that you're seeing in the layout with a plugin that you provide:

function HideTopbarPlugin() {
  // this plugin overrides the Topbar component to return nothing
  return {
    components: {
      Topbar: function() { return null }
    }
  }
}

SwaggerUIBundle({
  url: "http://petstore.swagger.io/v2/swagger.json",
  dom_id: '#swagger-ui',
  presets: [
    SwaggerUIBundle.presets.apis,
    SwaggerUIStandalonePreset
  ],
  plugins: [
    SwaggerUIBundle.plugins.DownloadUrl,
    HideTopbarPlugin
  ],
  layout: "StandaloneLayout"
})

I'm closing, but feel free to reply if you need anything.

All 14 comments

Hi Jay!

re: the dist folder, we have four files in dist now, which are explained in the release notes for v3.0.0, under the "Distribution files & usage" section.

You were correct! You don't need swagger-ui.js, the other three will provide everything you need.

As for customizing the look and feel, you'll want to customize the layout in /src/standalone/layout.jsx for that. That requires a full dev environment... we're working on documentation around this, but if you need guidance please reply and I'll help out.

If you want to hide the Swagger bar and be on your way, you can override the Topbar component that you're seeing in the layout with a plugin that you provide:

function HideTopbarPlugin() {
  // this plugin overrides the Topbar component to return nothing
  return {
    components: {
      Topbar: function() { return null }
    }
  }
}

SwaggerUIBundle({
  url: "http://petstore.swagger.io/v2/swagger.json",
  dom_id: '#swagger-ui',
  presets: [
    SwaggerUIBundle.presets.apis,
    SwaggerUIStandalonePreset
  ],
  plugins: [
    SwaggerUIBundle.plugins.DownloadUrl,
    HideTopbarPlugin
  ],
  layout: "StandaloneLayout"
})

I'm closing, but feel free to reply if you need anything.

Thanks, @shockey . Adding in that plugin helped and the top bar is gone.

If I want to make finer changes, like to descriptions or info things, do I modify a file like info.jsx, and then run npm run build, then replace the generated .js files?

You could do that- but IMO, a better way would be to create additional plugins that provide customized versions of those components.

Doing it this way (in files you create) keeps you from having to deal with merge conflicts in those core files down the road, when you decide to update to the latest version of Swagger-UI. Merge hell is not a good place to be 馃槃

Workflow would look like this:

  • create src/plugins/fooplugin directory
  • add custom components (info.jsx or whatever you want) to this folder
  • in src/plugins/fooplugin/index.js, import your custom components and provide them in a plugin (check out src/plugins/topbar/index.js for an example). Be aware of the name you use in the components object, it needs to exactly match the component you're overriding.
  • Import your plugin in src/standalone/index.js
  • npm run build
  • be on your way with the new dist folder!

You could also create your own plugin through your own build process, then pull it into Swagger-UI at runtime. You'd need Babel and Webpack, though- that's more guidance than I can provide in a comment. Be on the lookout for documentation around this 馃槃

Thanks for your help, @shockey ! I'll have to dig in and start playing around with this. Thanks for the detailed workflow.

Gah. Still struggling with this, @shockey . I'm trying to override info.jsx. I can make changes to the original one, but would prefer to make a plugin and override as you suggested above.

So, I created /plugins/info, which contains /index.js and /info.jsx - info.jsx is the original with changes I made. /core/components/info.jsx is back to its original state.

/plugins/info/index.js contains
```import Info from "./info.jsx"

export default function () {
return {
components: {
Info
}
}
}

/standalone/index.js contains:
```import StandaloneLayout from "./layout"
import "../style/main.scss"

import TopbarPlugin from "plugins/topbar"
import InfoPlugin from "plugins/info"

// the Standalone preset

let preset = [
  TopbarPlugin, InfoPlugin, 
  () => {
    return {
      components: { StandaloneLayout }
    }
  }
]

module.exports = preset

npm run build is successful, but I'm not getting any of the changes. I know it's something stupid but no luck so far. I based my plugins/info off of plugins/topbar.

@jaydreyer It is indeed a silly problem.... you need to return components: { info: Info }.

This is our fault, see here: https://github.com/swagger-api/swagger-ui/blob/master/src/core/presets/base.js#L69

We're not 100% consistent with how we're casing our components 馃槥 I'd love to change it, but it'd be a breaking change, which takes some planning.

Perfect! Thank you.

For removing Topbar just comment (TopbarPlugin) it in src/standalone/index.js, rebuild with npm run build or yarn build and thats it. For any other users/basic-coders would be easier to just disable it in index.html (e.g in constructor or so) rather than build your own build.

@to-kra, correct - some quick and dirty ways to disable the Topbar include setting the layout config option to BaseLayout, and adding a plugin that disables the Topbar component:

plugins: [
  () => {
    return {
      components: { Topbar: () => null }
    }
  }
]

I'm trying to follow the first example here, to replace the Topbar plugin. But when I do this, the whole page gets replaced with my plugin; the rest of the Swagger UI is gone. What am I doing wrong?

I'm using swagger-ui, not swagger-ui-dist, since it sounds like that's the recommended approach. But it's a little challenging, since all the examples seem to be for the dist version.

import SwaggerUI from 'swagger-ui';
import 'swagger-ui/dist/swagger-ui.css';
import StandalonePreset from 'swagger-ui/dist/swagger-ui-standalone-preset';
import React from "react";

const CustomTopbarPlugin = () => {
    return {
        components: {
            Topbar: () => <div>test</div>
        }
    }
};

SwaggerUI({
    dom_id: '#app',
    ...
    presets: [
        SwaggerUI.presets.apis,
        StandalonePreset
    ],
    plugins: [CustomTopbarPlugin],
    layout: 'StandaloneLayout',
    urls: [...]
});

@jacobweber, I believe this is happening because the Topbar <select> for the urls option actually drives the fetching of your API definitions. Without the Topbar driving that through user input, no definition ever gets loaded, so you get an empty screen.

FWIW, this is noted in the docs for urls:

urls: An array of API definition objects ({url: "", name: ""}) used by Topbar plugin.

This could be mitigated by fully wiring the urls option into state and having the topbar fire actions to control the current display, which would take a PR.

Is this something you need? If so, I can whip up a ticket for it.

OK, that makes sense. I don't think you need to open a ticket for it. My goal is to create a custom top bar, where I can select a URL as well as some other custom parameters needed for my spec. I can probably just replicate that URL-fetching logic in my own component, once I figure out how it works.

If you're taking requests, I'd be more interested in some more fleshed-out docs and examples around customizing the UI, including ones that use the recommended swagger-ui package instead of swagger-ui-dist.

If you're taking requests, I'd be more interested in some more fleshed-out docs and examples around customizing the UI, including ones that use the recommended swagger-ui package instead of swagger-ui-dist.

@jacobweber, almost everything is applicable to both, SwaggerUI vs SwaggerUIBundle is just a matter of whether third-party modules are included with our library - which one you should use depends on your project's build process. Can you point me to specific areas that give rise to this confusion?

Thanks!

Hi @shockey, I'm working on a custom plugin as well and wondering why my custom plugin is not found on window load.
I created plugins/operations-layout which contains operations-layout.jsx and index.js
plugins/operations-layout/operations-layout.jsx:

import React from "react"
class OperationsLayout extends React.Component {
  render() {
    const {
      getComponent
    } = this.props

    const Operations = getComponent("operations", true)

    return (
      <div className='swagger-ui'>
        <div>
          <Operations />
        </div>
      </div>
    );
  }
}

plugins/operations-layout/index.js:

import OperationsLayout from "./operations-layout.jsx"
const OperationsLayoutPlugin = () => {
  return {
    components: {
      OperationsLayout: OperationsLayout
    }
  }
}

plugins/index.js:

import Configs from "./configs"
import Topbar from "./topbar"
import OperationsLayoutPlugin from "./operations-layout"
export default {
  Configs,
  Topbar,
  OperationsLayoutPlugin,
}

standalone/index.js

import StandaloneLayout from "./layout"
import TopbarPlugin from "plugins/topbar"
import ConfigsPlugin from "corePlugins/configs"
import OperationsLayoutPlugin from "plugins/operations-layout"

let preset = [
  TopbarPlugin,
  ConfigsPlugin,
  OperationsLayoutPlugin,
  () => {
    return {
      components: { StandaloneLayout }
    }
  }
]
module.exports = preset

And in dev-helpers/index.html I have:

...
      const ui = SwaggerUIBundle({
        url: "https://petstore.swagger.io/v2/swagger.json",
        dom_id: '#swagger-ui',
        presets: [
          SwaggerUIBundle.presets.apis,
          SwaggerUIStandalonePreset
        ],
        plugins: [
          // SwaggerUIBundle.plugins.DownloadUrl,
          OperationsLayoutPlugin,
        ],
        // layout: "StandaloneLayout"
        layout: "OperationsLayout"
      })
...

But in the console the error is
Uncaught ReferenceError: OperationsLayoutPlugin is not defined at window.onload
What am I missing here??
Thank you!

Was this page helpful?
0 / 5 - 0 ratings