Skip to content

Commit b4b7306

Browse files
authored
Merge pull request #149 from qwikerx/feat/create-clipboard-component
feat: creact clipboard component
2 parents 10d1884 + f41bc5b commit b4b7306

File tree

22 files changed

+380
-91
lines changed

22 files changed

+380
-91
lines changed

README.md

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,11 @@ export default component$(() => {
206206
</td>
207207
</tr>
208208
<tr>
209+
<td>
210+
<a href="https://flowbite-qwik.com/docs/components/clipboard">
211+
<img alt="Qwik Clipboard" src="https://flowbite.s3.amazonaws.com/github/clipboard.jpg" />
212+
</a>
213+
</td>
209214
<td>
210215
<a href="https://flowbite-qwik.com/docs/components/drawer">
211216
<img alt="Qwik Drawer" src="https://flowbite.s3.amazonaws.com/github/drawer.jpg" />
@@ -216,13 +221,13 @@ export default component$(() => {
216221
<img alt="Qwik Dropdown" src="https://flowbite.s3.amazonaws.com/github/dropdown.jpg" />
217222
</a>
218223
</td>
224+
</tr>
225+
<tr>
219226
<td>
220227
<a href="https://flowbite-qwik.com/docs/components/footer">
221228
<img alt="Qwik Footer" src="https://flowbite.s3.amazonaws.com/github/footer.jpg" />
222229
</a>
223230
</td>
224-
</tr>
225-
<tr>
226231
<td>
227232
<a href="https://flowbite-qwik.com/docs/typography/hr">
228233
<img alt="Qwik HR" src="https://flowbite.s3.amazonaws.com/github/hr.jpg" />
@@ -233,13 +238,13 @@ export default component$(() => {
233238
<img alt="Qwik Heading" src="https://flowbite.s3.amazonaws.com/github/heading.jpg" />
234239
</a>
235240
</td>
241+
</tr>
242+
<tr>
236243
<td>
237244
<a href="https://flowbite-qwik.com/docs/forms/input">
238245
<img alt="Qwik Input" src="https://flowbite.s3.amazonaws.com/github/input-field.jpg" />
239246
</a>
240247
</td>
241-
</tr>
242-
<tr>
243248
<td>
244249
<a href="https://flowbite-qwik.com/docs/components/jumbotron">
245250
<img alt="Qwik Jumbotron" src="https://flowbite.s3.amazonaws.com/github/jumbotron.jpg" />
@@ -250,13 +255,13 @@ export default component$(() => {
250255
<img alt="Qwik Kbd" src="https://flowbite.s3.amazonaws.com/github/kbd.jpg" />
251256
</a>
252257
</td>
258+
</tr>
259+
<tr>
253260
<td>
254261
<a href="https://flowbite-qwik.com/docs/typography/link">
255262
<img alt="Qwik Link" src="https://flowbite.s3.amazonaws.com/github/link.jpg" />
256263
</a>
257264
</td>
258-
</tr>
259-
<tr>
260265
<td>
261266
<a href="https://flowbite-qwik.com/docs/typography/list">
262267
<img alt="Qwik List" src="https://flowbite.s3.amazonaws.com/github/list.jpg" />
@@ -267,13 +272,13 @@ export default component$(() => {
267272
<img alt="Qwik ListGroup" src="https://flowbite.s3.amazonaws.com/github/list-group.jpg" />
268273
</a>
269274
</td>
275+
</tr>
276+
<tr>
270277
<td>
271278
<a href="https://flowbite-qwik.com/docs/components/modal">
272279
<img alt="Qwik Modal" src="https://flowbite.s3.amazonaws.com/github/modal.jpg" />
273280
</a>
274281
</td>
275-
</tr>
276-
<tr>
277282
<td>
278283
<a href="https://flowbite-qwik.com/docs/components/navbar">
279284
<img alt="Qwik Navbar" src="https://flowbite.s3.amazonaws.com/github/navbar.jpg" />
@@ -284,13 +289,13 @@ export default component$(() => {
284289
<img alt="Qwik Pagination" src="https://flowbite.s3.amazonaws.com/github/pagination.jpg" />
285290
</a>
286291
</td>
292+
</tr>
293+
<tr>
287294
<td>
288295
<a href="https://flowbite-qwik.com/docs/forms/radio">
289296
<img alt="Qwik Radio" src="https://flowbite.s3.amazonaws.com/github/radio.jpg" />
290297
</a>
291298
</td>
292-
</tr>
293-
<tr>
294299
<td>
295300
<a href="https://flowbite-qwik.com/docs/components/rating">
296301
<img alt="Qwik Rating" src="https://flowbite.s3.amazonaws.com/github/rating.jpg" />
@@ -301,13 +306,13 @@ export default component$(() => {
301306
<img alt="Qwik Select" src="https://flowbite.s3.amazonaws.com/github/select.jpg" />
302307
</a>
303308
</td>
309+
</tr>
310+
<tr>
304311
<td>
305312
<a href="https://flowbite-qwik.com/docs/components/sidebar">
306313
<img alt="Qwik Sidebar" src="https://flowbite.s3.amazonaws.com/github/sidebar.jpg" />
307314
</a>
308315
</td>
309-
</tr>
310-
<tr>
311316
<td>
312317
<a href="https://flowbite-qwik.com/docs/components/spinner">
313318
<img alt="Qwik Spinner" src="https://flowbite.s3.amazonaws.com/github/spinner.jpg" />
@@ -318,13 +323,13 @@ export default component$(() => {
318323
<img alt="Qwik Table" src="https://flowbite.s3.amazonaws.com/github/tables.jpg" />
319324
</a>
320325
</td>
326+
</tr>
327+
<tr>
321328
<td>
322329
<a href="https://flowbite-qwik.com/docs/components/tabs">
323330
<img alt="Qwik Tabs" src="https://flowbite.s3.amazonaws.com/github/tabs.jpg" />
324331
</a>
325332
</td>
326-
</tr>
327-
<tr>
328333
<td>
329334
<a href="https://flowbite-qwik.com/docs/forms/textarea">
330335
<img alt="Qwik Textarea" src="https://flowbite.s3.amazonaws.com/github/textarea.jpg" />
@@ -335,20 +340,19 @@ export default component$(() => {
335340
<img alt="Qwik ToastList" src="https://flowbite.s3.amazonaws.com/github/toast.jpg" />
336341
</a>
337342
</td>
343+
</tr>
344+
<tr>
338345
<td>
339346
<a href="https://flowbite-qwik.com/docs/forms/toggle">
340347
<img alt="Qwik Toggle" src="https://flowbite.s3.amazonaws.com/github/toggle.jpg" />
341348
</a>
342349
</td>
343-
</tr>
344-
<tr>
345350
<td>
346351
<a href="https://flowbite-qwik.com/docs/components/tooltip">
347352
<img alt="Qwik Tooltip" src="https://flowbite.s3.amazonaws.com/github/tooltips.jpg" />
348353
</a>
349354
</td>
350355
<td></td>
351-
<td></td>
352356
</tr>
353357
</table>
354358
</div>

apps/web/src/components/DocumentPage/DocumentPages.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ export const DocumentPage = component$(() => {
1313
const sections = useStore<Array<string>>([])
1414

1515
useVisibleTask$(() => {
16-
const sectionsTitles = document.querySelectorAll('h2')
17-
sectionsTitles.forEach((sectionTitle) => {
16+
const sectionsTitles = page.value?.querySelectorAll('h2')
17+
18+
sectionsTitles?.forEach((sectionTitle) => {
1819
const slug = toSlug(sectionTitle.textContent || '')
1920
sections.push(sectionTitle.textContent || '')
2021
sectionTitle.setAttribute('id', slug)

apps/web/src/components/homepage/ComponentSection/components.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export const componentsNaming: Record<string, { folder: string; img: string; doc
1111
Card: { folder: 'components', img: 'cards', doc: 'card' },
1212
Carousel: { folder: 'components', img: 'carousel', doc: 'carousel' },
1313
Checkbox: { folder: 'forms', img: 'checkbox', doc: 'checkbox' },
14+
Clipboard: { folder: 'components', img: 'clipboard', doc: 'clipboard' },
1415
Drawer: { folder: 'components', img: 'drawer', doc: 'drawer' },
1516
Dropdown: { folder: 'components', img: 'dropdown', doc: 'dropdown' },
1617
Footer: { folder: 'components', img: 'footer', doc: 'footer' },
Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,18 @@
1-
import { Input, Tooltip } from 'flowbite-qwik'
2-
import { $, component$, useSignal } from '@builder.io/qwik'
3-
import { IconClipboardCheckSolid } from 'flowbite-qwik-icons'
1+
import { Input, Clipboard } from 'flowbite-qwik'
2+
import { component$, useSignal } from '@builder.io/qwik'
43

54
type CopyPackageInputProps = {
65
value: string
76
}
87

98
export const CopyPackageInput = component$<CopyPackageInputProps>(({ value }) => {
10-
const copy = useSignal('')
11-
const justCopied = useSignal(false)
12-
13-
const copyToClipboard = $(() => {
14-
justCopied.value = true
15-
navigator.clipboard.writeText(value)
16-
setTimeout(() => (justCopied.value = false), 2000)
17-
})
9+
const inputValue = useSignal('')
1810

1911
return (
20-
<Tooltip style="dark">
21-
<Input
22-
bind:value={copy}
23-
q:slot="trigger"
24-
onClick$={copyToClipboard}
25-
placeholder={value}
26-
readOnly
27-
suffix={<IconClipboardCheckSolid />}
28-
size="md"
29-
/>
12+
<div class="w-full relative">
13+
<Input placeholder={value} bind:value={inputValue} disabled readOnly class="w-full" />
3014

31-
<div q:slot="content">{justCopied.value ? 'Copied!' : 'Copy to clipboard'}</div>
32-
</Tooltip>
15+
<Clipboard.WithIcon valueToCopy={value} class="absolute end-2 top-1/2 inline-flex -translate-y-1/2" />
16+
</div>
3317
)
3418
})

apps/web/src/generated-docs.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export const allDocs = {
1414
'button-group',
1515
'card',
1616
'carousel',
17+
'clipboard',
1718
'drawer',
1819
'dropdown',
1920
'footer',

apps/web/src/generated-examples.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,34 @@ export const examples: Record<string, Example[]> = {
813813
height: '100',
814814
},
815815
],
816+
clipboard: [
817+
{
818+
title: 'Default copy to clipboard',
819+
description: 'Use this example to copy the content of an input text field by clicking on a button and update the button text.',
820+
url: '/examples/[theme-rtl]/clipboard/01-default',
821+
content:
822+
'import { component$, useSignal } from \'@builder.io/qwik\'\nimport { Clipboard, Input } from \'flowbite-qwik\'\n\nexport default component$(() => {\n const inputValue = useSignal(\'\')\n return (\n <>\n <div class="flex gap-3 pt-8 max-w-80">\n <Input placeholder="npm install flowbite-qwik" bind:value={inputValue} disabled readOnly class="block w-full" />\n <Clipboard valueToCopy="npm install flowbite-react" label="Copy" class="h-full" />\n </div>\n </>\n )\n})',
823+
height: '200',
824+
},
825+
{
826+
title: 'Input with copy button',
827+
description:
828+
'This example can be used to copy the content of an input field by clicking on a button with an icon positioned inside the form element and also show a tooltip with a message when the text has been copied.',
829+
url: '/examples/[theme-rtl]/clipboard/02-with-icon',
830+
content:
831+
'import { component$, useSignal } from \'@builder.io/qwik\'\nimport { Clipboard, Input } from \'flowbite-qwik\'\n\nexport default component$(() => {\n const inputValue = useSignal(\'\')\n return (\n <div class="grid w-full max-w-64 pt-8">\n <div class="relative">\n <Input placeholder="npm install flowbite-qwik" bind:value={inputValue} disabled readOnly class="col-span-6 block w-full" />\n\n <Clipboard.WithIcon valueToCopy="npm install flowbite-react" class="absolute end-2 top-1/2 inline-flex -translate-y-1/2" />\n </div>\n </div>\n )\n})',
832+
height: '200',
833+
},
834+
{
835+
title: 'Copy button with text',
836+
description:
837+
'Use this example to show a copy button inside the input field with a text label and icon that updates to a success state when the text has been copied.',
838+
url: '/examples/[theme-rtl]/clipboard/03-with-icon-text',
839+
content:
840+
'import { component$, useSignal } from \'@builder.io/qwik\'\nimport { Clipboard, Input } from \'flowbite-qwik\'\n\nexport default component$(() => {\n const inputValue = useSignal(\'\')\n return (\n <div className="grid w-full max-w-80 pt-8">\n <div class="relative">\n <Input placeholder="npm install flowbite-qwik" bind:value={inputValue} disabled readOnly class="col-span-6 block w-full" />\n\n <Clipboard.WithIconText valueToCopy="npm install flowbite-react" class="absolute end-2 top-1/2 inline-flex -translate-y-1/2" />\n </div>\n </div>\n )\n})',
841+
height: '200',
842+
},
843+
],
816844
drawer: [
817845
{
818846
title: 'Drawer',
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { component$ } from '@builder.io/qwik'
2+
import { Hr } from 'flowbite-qwik'
3+
import { ComponentDocPage } from '~/components/ComponentDocPage/ComponentDocPage'
4+
5+
export default component$(() => {
6+
return (
7+
<ComponentDocPage name="clipboard">
8+
<div q:slot="description">
9+
Use the clipboard component to copy text, data or lines of code to the clipboard with a single click based on various styles and examples
10+
coded with Tailwind CSS and Flowbite
11+
<Hr />
12+
The copy to clipboard component allows you to copy text, lines of code, contact details or any other data to the clipboard with a single click
13+
on a trigger element such as a button. This component can be used to copy text from an input field, textarea, code block or even address
14+
fields in a form element. These components are built with Tailwind CSS and Flowbite Qwik and can be found on the internet on websites such as
15+
Bitly, Cloudflare, Amazon AWS and almost all open-source projects and documentations.
16+
</div>
17+
</ComponentDocPage>
18+
)
19+
})
20+
21+
export const head = () => ({
22+
title: 'Qwik Clipboard - Flowbite',
23+
meta: [
24+
{
25+
name: 'description',
26+
content:
27+
'The copy to clipboard component allows you to copy text, lines of code, contact details or any other data to the clipboard with a single click on a trigger element such as a button',
28+
},
29+
],
30+
})

apps/web/src/routes/docs/getting-started/introduction/index.tsx

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,27 @@ export default component$(() => {
2020
<Link target="_blank" rel="noreferrer" href="https://github.com/qwikerx/flowbite-qwik">
2121
Flowbite Qwik
2222
</Link>{' '}
23-
is a free and open-source UI component library based on the core{' '}
23+
is a free and open-source UI component library based on the core Flowbite components and built with native Qwik components and
24+
interactivity handling.
2425
<Link href="https://flowbite.com/" target="_blank" rel="noreferrer">
2526
Flowbite
2627
</Link>{' '}
2728
components and built with Qwik components and interactivity handling.
2829
</p>
30+
<p>
31+
This library features hundreds of interactive elements such as navbars, dropdowns, modals, and sidebars all handled by Svelte and based on
32+
the utility classes from Tailwind CSS.
33+
</p>
34+
<Heading tag="h2">Getting started</Heading>
35+
<p>
36+
Learn how to get started with Flowbite Qwik by following the quickstart guide and start leveraging the interactive Qwik components coupled
37+
with Flowbite and Tailwind CSS.
38+
</p>
39+
<Button tag={Link} href="/docs/getting-started/quickstart" size="lg">
40+
Get started
41+
</Button>
2942
</div>
3043
</DocumentPage>
31-
<Button tag={Link} href="/docs/getting-started/quickstart" class="mt-8">
32-
Quickstart
33-
</Button>
3444
</>
3545
)
3646
})
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* title: Default copy to clipboard
3+
* description: Use this example to copy the content of an input text field by clicking on a button and update the button text.
4+
* height: 200
5+
*/
6+
7+
import { component$, useSignal } from '@builder.io/qwik'
8+
import { staticGenerateHandler } from '~/routes/examples/layout'
9+
import { StaticGenerateHandler } from '@builder.io/qwik-city'
10+
import { Clipboard, Input } from 'flowbite-qwik'
11+
12+
export default component$(() => {
13+
const inputValue = useSignal('')
14+
return (
15+
<>
16+
<div class="flex gap-3 pt-8 max-w-80">
17+
<Input placeholder="npm install flowbite-qwik" bind:value={inputValue} disabled readOnly class="block w-full" />
18+
<Clipboard valueToCopy="npm install flowbite-react" label="Copy" class="h-full" />
19+
</div>
20+
</>
21+
)
22+
})
23+
24+
export const onStaticGenerate: StaticGenerateHandler = async () => {
25+
return staticGenerateHandler()
26+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* title: Input with copy button
3+
* description: This example can be used to copy the content of an input field by clicking on a button with an icon positioned inside the form element and also show a tooltip with a message when the text has been copied.
4+
* height: 200
5+
*/
6+
7+
import { component$, useSignal } from '@builder.io/qwik'
8+
import { staticGenerateHandler } from '~/routes/examples/layout'
9+
import { StaticGenerateHandler } from '@builder.io/qwik-city'
10+
import { Clipboard, Input } from 'flowbite-qwik'
11+
12+
export default component$(() => {
13+
const inputValue = useSignal('')
14+
return (
15+
<div class="grid w-full max-w-64 pt-8">
16+
<div class="relative">
17+
<Input placeholder="npm install flowbite-qwik" bind:value={inputValue} disabled readOnly class="col-span-6 block w-full" />
18+
19+
<Clipboard.WithIcon valueToCopy="npm install flowbite-react" class="absolute end-2 top-1/2 inline-flex -translate-y-1/2" />
20+
</div>
21+
</div>
22+
)
23+
})
24+
export const onStaticGenerate: StaticGenerateHandler = async () => {
25+
return staticGenerateHandler()
26+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* title: Copy button with text
3+
* description: Use this example to show a copy button inside the input field with a text label and icon that updates to a success state when the text has been copied.
4+
* height: 200
5+
*/
6+
7+
import { component$, useSignal } from '@builder.io/qwik'
8+
import { staticGenerateHandler } from '~/routes/examples/layout'
9+
import { StaticGenerateHandler } from '@builder.io/qwik-city'
10+
import { Clipboard, Input } from 'flowbite-qwik'
11+
12+
export default component$(() => {
13+
const inputValue = useSignal('')
14+
return (
15+
<div className="grid w-full max-w-80 pt-8">
16+
<div class="relative">
17+
<Input placeholder="npm install flowbite-qwik" bind:value={inputValue} disabled readOnly class="col-span-6 block w-full" />
18+
19+
<Clipboard.WithIconText valueToCopy="npm install flowbite-react" class="absolute end-2 top-1/2 inline-flex -translate-y-1/2" />
20+
</div>
21+
</div>
22+
)
23+
})
24+
export const onStaticGenerate: StaticGenerateHandler = async () => {
25+
return staticGenerateHandler()
26+
}

0 commit comments

Comments
 (0)