Skip to content

Commit

Permalink
Make guide for tailwind more verbose (gradio-app#8152)
Browse files Browse the repository at this point in the history
  • Loading branch information
duerrsimon authored Apr 30, 2024
1 parent 9a5728c commit 989fe25
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 65 deletions.
5 changes: 5 additions & 0 deletions .changeset/four-crabs-rescue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"website": minor
---

feat:Make guide for tailwind more verbose
94 changes: 86 additions & 8 deletions guides/05_custom-components/05_frontend.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export let mode: "static" | "interactive";

A minimal `Index.svelte` file would look like:

```typescript
```svelte
<script lang="ts">
import type { LoadingStatus } from "@gradio/statustracker";
import { Block } from "@gradio/atoms";
Expand Down Expand Up @@ -119,7 +119,7 @@ The `Example.svelte` file should expose the following props:

This is the `Example.svelte` file for the code `Radio` component:

```typescript
```svelte
<script lang="ts">
export let value: string;
export let type: "gallery" | "table";
Expand Down Expand Up @@ -154,9 +154,8 @@ The `upload` function will upload an array of `FileData` values to the server.
Here's an example of loading files from an `<input>` element when its value changes.


```typescript
```svelte
<script lang="ts">

import { upload, prepare_files, type FileData } from "@gradio/client";
export let root;
export let value;
Expand Down Expand Up @@ -218,7 +217,7 @@ This means that you can use them to save yourself time while incorporating commo
For example, the `@gradio/upload` package has `Upload` and `ModifyUpload` components for properly uploading files to the Gradio server.
Here is how you can use them to create a user interface to upload and display PDF files.

```typescript
```svelte
<script>
import { type FileData, Upload, ModifyUpload } from "@gradio/upload";
import { Empty, UploadText, BlockLabel } from "@gradio/atoms";
Expand Down Expand Up @@ -267,23 +266,102 @@ Vite options:

Svelte options:
- `preprocess`: A list of svelte preprocessors to use.
- `extensions`: A list of file extensions to compile to `.svelte` files.

The `gradio.config.js` file should be placed in the root of your component's `frontend` directory. A default config file is created for you when you create a new component. But you can also create your own config file, if one doesn't exist, and use it to customize your component's build process.

### Example for a Vite plugin

The `gradio.config.js` file should be placed in the root of your component's `frontend` directory. A default config file is created for you when you create a new component. But you can also create your own config file and use it to customize your component's build process.
Custom components can use Vite plugins to customize the build process. Check out the [Vite Docs](https://vitejs.dev/guide/using-plugins.html) for more information.

Here we configure [TailwindCSS](https://tailwindcss.com), a utility-first CSS framework. Setup is easiest using the version 4 prerelease.

```
npm install tailwindcss@next @tailwindcss/vite@next
```

In `gradio.config.js`:

```typescript
import tailwindcss from "@tailwindcss/vite";
export default {
plugins: [tailwindcss()]
};
```

Then create a `style.css` file with the following content:

```css
@import "tailwindcss";
```

Import this file into `Index.svelte`. Note, that you need to import the css file containing `@import` and cannot just use a `<style>` tag and use `@import` there.

```svelte
<script lang="ts">
[...]
import "./style.css";
[...]
</script>
```

### Example for Svelte options

In `gradio.config.js` you can also specify a some Svelte options to apply to the Svelte compilation. In this example we will add support for [`mdsvex`](https://mdsvex.pngwn.io), a Markdown preprocessor for Svelte.

In order to do this we will need to add a [Svelte Preprocessor](https://svelte.dev/docs/svelte-compiler#preprocess) to the `svelte` object in `gradio.config.js` and configure the [`extensions`](https://github.com/sveltejs/vite-plugin-svelte/blob/HEAD/docs/config.md#config-file) field. Other options are not currently supported.

First, install the `mdsvex` plugin:

```bash
npm install mdsvex
```

Then add the following to `gradio.config.js`:

```typescript
import { mdsvex } from "mdsvex";

export default {
plugins: [tailwindcss()],
svelte: {
preprocess: [
mdsvex()
]
],
extensions: [".svelte", ".svx"]
}
};
```

Now we can create `mdsvex` documents in our component's `frontend` directory and they will be compiled to `.svelte` files.

```md
<!-- HelloWorld.svx -->

<script lang="ts">
import { Block } from "@gradio/atoms";

export let title = "Hello World";
</script>

<Block label="Hello World">

# {title}

This is a markdown file.

</Block>
```

We can then use the `HelloWorld.svx` file in our components:

```svelte
<script lang="ts">
import HelloWorld from "./HelloWorld.svx";
</script>
<HelloWorld />
```

## Conclusion

You now how to create delightful frontends for your components!
Expand Down
18 changes: 9 additions & 9 deletions guides/05_custom-components/07_pdf-component-example.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ Navigate to `Index.svelte` and delete mentions of `JSONView`
import { JsonView } from "@zerodevx/svelte-json-view";
```

```ts
```svelte
<JsonView json={value} />
```

Expand Down Expand Up @@ -148,7 +148,7 @@ If it is loaded, we want to display it underneath a "clear" button that lets our
We're going to use the `Upload` and `ModifyUpload` components that come with the `@gradio/upload` package to do this.
Underneath the `</script>` tag, delete all the current code and add the following:

```ts
```svelte
<Block {visible} {elem_id} {elem_classes} {container} {scale} {min_width}>
{#if loading_status}
<StatusTracker
Expand Down Expand Up @@ -192,7 +192,7 @@ Its creating a new div to display our "upload text" with some custom styling.
Tip: Notice that we're leveraging Gradio core's existing css variables here: `var(--size-60)` and `var(--body-text-color-subdued)`. This allows our component to work nicely in light mode and dark mode, as well as with Gradio's built-in themes.


```ts
```svelte
<script lang="ts">
import { Upload as UploadIcon } from "@gradio/icons";
export let hovered = false;
Expand Down Expand Up @@ -243,7 +243,7 @@ Tip: Notice that we're leveraging Gradio core's existing css variables here: `va

Now import `PdfUploadText.svelte` in your `<script>` and pass it to the `Upload` component!

```ts
```svelte
import PdfUploadText from "./PdfUploadText.svelte";
...
Expand Down Expand Up @@ -330,15 +330,15 @@ Tip: The `$:` syntax in svelte is how you declare statements to be reactive. Whe

Now place the `canvas` underneath the `ModifyUpload` component:

```ts
```svelte
<div class="pdf-canvas" style="height: {height}px">
<canvas bind:this={canvasRef}></canvas>
</div>
```

And add the following styles to the `<style>` tag:

```ts
```svelte
<style>
.pdf-canvas {
display: flex;
Expand Down Expand Up @@ -373,7 +373,7 @@ Tip: The `gradio.dispatch` method is actually what is triggering the `change` or

Now we will run these functions whenever the `Upload` component uploads a file and whenever the `ModifyUpload` component clears the current file. The `<Upload>` component dispatches a `load` event with a payload of type `FileData` corresponding to the uploaded file. The `on:load` syntax tells `Svelte` to automatically run this function in response to the event.

```ts
```svelte
<ModifyUpload i18n={gradio.i18n} on:clear={handle_clear} absolute />
...
Expand Down Expand Up @@ -424,7 +424,7 @@ Import the `BaseButton` and add the following functions that will render the nex

Now we will add them underneath the canvas in a separate `<div>`

```ts
```svelte
...
<ModifyUpload i18n={gradio.i18n} on:clear={handle_clear} absolute />
Expand Down Expand Up @@ -469,7 +469,7 @@ We're going to want users of our component to get a preview of the PDF if its us
To do so, we're going to add some of the pdf rendering logic in `Index.svelte` to `Example.svelte`.


```ts
```svelte
<script lang="ts">
export let value: string;
export let type: "gallery" | "table";
Expand Down
4 changes: 2 additions & 2 deletions guides/05_custom-components/08_multimodal-chatbot-part1.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ Now for the fun part, actually rendering the text and files in the same message!

You should see some code like the following that determines whether a file or a markdown message should be displayed depending on the type of the message:

```ts
```svelte
{#if typeof message === "string"}
<Markdown
{message}
Expand All @@ -248,7 +248,7 @@ You should see some code like the following that determines whether a file or a

We will modify this code to always display the text message and then loop through the files and display all of them that are present:

```ts
```svelte
<Markdown
message={message.text}
{latex_delimiters}
Expand Down
3 changes: 2 additions & 1 deletion js/_website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"@sveltejs/adapter-vercel": "^5.3.0",
"hast-util-to-string": "^3.0.0",
"mdsvex": "^0.11.0",
"postcss": ">=8.3.3 <9.0.0"
"postcss": ">=8.3.3 <9.0.0",
"prism-svelte": "^0.5.0"
}
}
53 changes: 8 additions & 45 deletions js/_website/src/routes/[[version]]/guides/[guide]/+page.server.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,10 @@
import { compile } from "mdsvex";
import { compile, code_highlighter } from "mdsvex";
import anchor from "$lib/assets/img/anchor.svg";
import { make_slug_processor } from "$lib/utils";
import { toString as to_string } from "hast-util-to-string";
import { redirect } from "@sveltejs/kit";
import { error } from "@sveltejs/kit";

import Prism from "prismjs";
import "prismjs/components/prism-python";
import "prismjs/components/prism-bash";
import "prismjs/components/prism-json";
import "prismjs/components/prism-typescript";
import "prismjs/components/prism-csv";
import "prismjs/components/prism-markup";
import "prismjs/components/prism-javascript";
import "prismjs/components/prism-toml";
import "prismjs/components/prism-docker";

const langs = {
python: "python",
py: "python",
bash: "bash",
csv: "csv",
html: "html",
shell: "bash",
json: "json",
javascript: "javascript",
js: "javascript",
typescript: "typescript",
ts: "typescript",
directory: "json",
toml: "toml",
docker: "docker",
dockerfile: "docker"
};

function highlight(code: string, lang: string | undefined) {
const _lang = langs[lang as keyof typeof langs] || "";

const highlighted = _lang
? `<div class="codeblock"><pre class="language-${lang}"><code>${Prism.highlight(
code,
Prism.languages[_lang],
_lang
)}</code></pre></div>`
: code;

return highlighted;
}

import version from "$lib/json/version.json";
export const prerender = true;

Expand Down Expand Up @@ -151,7 +108,13 @@ export async function load({ params, url }) {
const compiled = await compile(guide.content, {
rehypePlugins: [plugin],
highlight: {
highlighter: highlight
highlighter: async (code, lang) => {
const h = (await code_highlighter(code, lang, "")).replace(
/\{@html `|`\}/g,
""
);
return `<div class="codeblock">${h}</div>`;
}
}
});
guide.new_html = compiled?.code;
Expand Down
7 changes: 7 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 989fe25

Please sign in to comment.