{"id":18555277,"url":"https://github.com/gugadev/storify","last_synced_at":"2025-04-09T23:32:11.024Z","repository":{"id":37732439,"uuid":"170141139","full_name":"gugadev/storify","owner":"gugadev","description":"Instagram/Whatsapp stories clone built on Web Components and Web Animations API. 🔥","archived":false,"fork":false,"pushed_at":"2022-12-10T00:31:44.000Z","size":2669,"stargazers_count":95,"open_issues_count":25,"forks_count":19,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-01T10:44:20.262Z","etag":null,"topics":["custom-elements","javascript","postcss","typescript","web-animations","web-animations-api","web-components","webpack"],"latest_commit_sha":null,"homepage":"https://gugadev.github.io/storify","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gugadev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-02-11T14:19:25.000Z","updated_at":"2024-12-04T22:36:11.000Z","dependencies_parsed_at":"2023-01-26T01:02:04.111Z","dependency_job_id":null,"html_url":"https://github.com/gugadev/storify","commit_stats":null,"previous_names":["gugadev/wc-stories"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gugadev%2Fstorify","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gugadev%2Fstorify/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gugadev%2Fstorify/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gugadev%2Fstorify/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gugadev","download_url":"https://codeload.github.com/gugadev/storify/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248129905,"owners_count":21052658,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["custom-elements","javascript","postcss","typescript","web-animations","web-animations-api","web-components","webpack"],"created_at":"2024-11-06T21:25:54.698Z","updated_at":"2025-04-09T23:32:10.471Z","avatar_url":"https://github.com/gugadev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003ewc 🌐 stories\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\nInstagram/Whatsapp stories like built on Web Components and Web Animations API.\n\u003c/p\u003e\n\n\u003cbr /\u003e\n\n\u003c!--\n```\n\u003ccustom-element-demo\u003e\n  \u003ctemplate\u003e\n    \u003chead\u003e\n      \u003cscript src=\"https://unpkg.com/web-animations-js@2.3.1/web-animations.min.js\"\u003e\u003c/script\u003e\n      \u003cscript src=\"https://unpkg.com/@webcomponents/webcomponentsjs@2.2.7/custom-elements-es5-adapter.js\"\u003e\u003c/script\u003e\n      \u003cscript src=\"https://unpkg.com/@webcomponents/webcomponentsjs@2.2.7/webcomponents-loader.js\"\u003e\u003c/script\u003e\n      \u003cscript defer src=\"https://unpkg.com/@gugadev/wc-stories@0.0.3/index.js\"\u003e\u003c/script\u003e\n    \u003c/head\u003e\n    \u003cwc-stories width=\"320\" height=\"480\" withShadow\u003e\n      \u003cwc-stories-story src=\"https://gugadev.github.io/wc-stories/img/01.jpg\"\u003e\u003c/wc-stories-story\u003e\n      \u003cwc-stories-story src=\"https://gugadev.github.io/wc-stories/img/02.jpg\"\u003e\u003c/wc-stories-story\u003e\n      \u003cwc-stories-story src=\"https://gugadev.github.io/wc-stories/img/03.jpg\"\u003e\u003c/wc-stories-story\u003e\n      \u003cwc-stories-story src=\"https://gugadev.github.io/wc-stories/img/04.jpg\"\u003e\u003c/wc-stories-story\u003e\n      \u003cwc-stories-story src=\"https://gugadev.github.io/wc-stories/img/05.jpg\"\u003e\u003c/wc-stories-story\u003e\n    \u003c/wc-stories\u003e\n  \u003c/template\u003e\n\u003c/custom-element-demo\u003e\n```\n--\u003e\n\n\n## Demos\n\n| [\u003cimg src=\"https://i.imgur.com/BNb7jEK.png?1\" height=\"24\"/\u003e]() \u003cbr/\u003eVanilla JS | [\u003cimg src=\"https://i.imgur.com/PWBviOu.png?1\" height=\"24\"/\u003e]() \u003cbr/\u003e Angular | [\u003cimg src=\"https://i.imgur.com/vttMVID.png?1\" height=\"24\"/\u003e]() \u003cbr/\u003e React | [\u003cimg src=\"https://i.imgur.com/Xfm7eKj.png?1\" height=\"24\"/\u003e]() \u003cbr/\u003e Vue |\n|------------|---------|-------|-----|\n| \u003ca href=\"https://gugadev.github.io/wc-stories\" target=\"_blank\"\u003eLink\u003c/a\u003e          | \u003ca href=\"https://angular-yhsvse.stackblitz.io/\" target=\"_blank\"\u003eLink\u003c/a\u003e       | \u003ca href=\"https://react-zf2tfr.stackblitz.io/\" target=\"_blank\"\u003eLink\u003c/a\u003e     | \u003ca href=\"https://vue-et4qky.stackblitz.io/\" target=\"_blank\"\u003eLink\u003c/a\u003e   |\n\n## Browser support\n\n| [\u003cimg src=\"https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png\" alt=\"IE / Edge\" width=\"24px\" height=\"24px\" /\u003e](http://godban.github.io/browsers-support-badges/)\u003c/br\u003eIE / Edge | [\u003cimg src=\"https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png\" alt=\"Firefox\" width=\"24px\" height=\"24px\" /\u003e](http://godban.github.io/browsers-support-badges/)\u003c/br\u003eFirefox | [\u003cimg src=\"https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png\" alt=\"Chrome\" width=\"24px\" height=\"24px\" /\u003e](http://godban.github.io/browsers-support-badges/)\u003c/br\u003eChrome | [\u003cimg src=\"https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png\" alt=\"Safari\" width=\"24px\" height=\"24px\" /\u003e](http://godban.github.io/browsers-support-badges/)\u003c/br\u003eSafari | [\u003cimg src=\"https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png\" alt=\"Opera\" width=\"24px\" height=\"24px\" /\u003e](http://godban.github.io/browsers-support-badges/)\u003c/br\u003eOpera |\n| --------- | --------- | --------- | --------- | --------- |\n| IE11, Edge| last 10 versions| last 10 versions| last 10 versions| last 10 versions\n\n---\n\n## 📦 Install\n\n```bash\nnpm i @gugadev/wc-stories\n```\n\n## 💡 What's the prupose of it?\n\nJust fun 🙂. I love learn and code, so, this every time I have free time, pick some crazy idea or got inspiration from another projects and make it. 😋\n\n## 🦄 Inspiration\n\nWhen I saw the project of Mohit, [react-insta-stories](https://github.com/mohitk05/react-insta-stories), immediately wanted to know how complicated it would be to do the same thing using **Web Components**. So, I built this. Thanks, Mohit! 😃 \n\n## ⚙️ How it works?\n\nThere are three components working together:\n\n- `\u003cwc-stories-story\u003e`: this component shows a image. The maximun size of an image is the containers viewport.\n- `\u003cwc-stories-progress`\u003e: this component shows the progress bar at top the the container. It uses **Web Animations API** to run it. If we change of image (clicking on left/right), the previous animation is cancelled.\n- `\u003cwc-stories\u003e`: this is the main component. This one harbor the two components above. Here is the logic for control which image should be revealed, what happen if the user\nclicks on left or right side, etc.\n\n## 🚀 How to run?\n\nAfter install depenencies, you just need to run `yarn start`. Once the server was started, go to [localhost:4444](http://127.0.0.1:4444) and see it in action.\n\n## 🛠️ How to build?\n\nExecute the `yarn build` command to compile the source code and get the ES5 equivalent. Compiled code will be available on `dist/` folder.\n\n## 🙋 How to use it in my web/app?\n\nFirst, we need to add the needed polyfills:\n\n- `@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js`\n- `@webcomponents/webcomponentsjs/webcomponents-loader.js`.\n- `web-animations-js/web-animations.min.js`\n\n### Web Components/Vanilla JavaScript\nIf you're using Web Components or vanilla JavaScript, just put the `wc-stories` tag inside your HTML and pass it the array of images:\n\n```html\n\u003cwc-stories height=\"480\" width=\"320\" withShadow\u003e\n  \u003cwc-stories-story src=\"/img/01.jpg\"\u003e\u003c/wc-stories-story\u003e\n  \u003cwc-stories-story src=\"/img/02.jpg\"\u003e\u003c/wc-stories-story\u003e\n  \u003cwc-stories-story src=\"/img/03.jpg\"\u003e\u003c/wc-stories-story\u003e\n  \u003cwc-stories-story src=\"/img/04.jpg\"\u003e\u003c/wc-stories-story\u003e\n  \u003cwc-stories-story src=\"/img/05.jpg\"\u003e\u003c/wc-stories-story\u003e\n\u003c/wc-stories\u003e\n```\n\n### React\n\nIf you're using React, use the component as is. Instead of passing raw values you can use `state` to\nstore the component configuration:\n\n```javascript\nexport class MyComponent extends React.Component {\n  this.state = {\n    width: 320,\n    height: 480,\n    withShadow: true,\n    stories: [\n      '/path/to/image',\n      '/path/to/image',\n      '/path/to/image',\n      ...\n    ]\n  }\n  render() {\n    return (\n      \u003cwc-stories\n        width={this.state.height}\n        height={this.state.width}\n        withShadow={this.state.withShadow}\n      \u003e\n      {\n        this.state.stories.map(story =\u003e (\n          \u003cwc-stories-story src={story} /\u003e\n        ))\n      }\n      \u003c/wc-stories\u003e\n    )\n  }\n}\n```\n\n### Angular\n\nIf you're using Angular, put the component inside your template. Like React, you can put the configuration inside the controller instead passing raw values:\n\n```html\n\u003ctemplate\u003e\n  ...\n  \u003cwc-stories [width]=\"storiesWidth\" [height]=\"storiesHeight\" withShadow\u003e\n    \u003cwc-stories-story *ngFor=\"let story of stories\" [src]=\"story\"\u003e\n    \u003c/wc-stories-story\u003e\n  \u003c/wc-stories\u003e\n\u003c/template\u003e\n```\n\n```typescript\n@Component({\n  ...\n})\nclass MyComponent implements OnInit {\n\n  ngOnInit() {\n    stories = [\n      '/path/to/image',\n      '/path/to/image',\n      '/path/to/image',\n      ...\n    ]\n  }\n}\n```\n\n###  Vue\n\nIf you're using Vue, put the component inside your template. Like React, you can put the configuration inside the controller instead passing raw values:\n\n```html\n\u003cwc-stories :width=\"storiesWidth\" :height=\"storiesHeigh\" :withShadow=\"withShadow\"\u003e\n  \u003cwc-stories-story v-if=\"story of stories\" :src=\"story\"\u003e\u003c/wc-stories\u003e\n\u003c/wc-stories\u003e\n```\n\n```javascript\nexport default {\n  data: () =\u003e ({\n    width: 320,\n    height: 480,\n    withShadow: tre,\n    stories: [\n      '/path/to/image',\n      '/path/to/image',\n      '/path/to/image',\n      ...\n    ]\n  })\n}\n```\n\n## 🆕 Lazy Loading\n\nThere are several ways to lazy loading images like _Low quality image placeholders_ and _progressive images_. This feature relies on the first one, so, in order to enable it, you need to pass, along with the images, the placeholders too.\n\n**Tip:** you can generate lightweight svg LQIP from high resolution images using [sqip](https://github.com/technopagan/sqip).\n\n```html\n\u003cwc-stories height=\"667\" width=\"375\" withShadow\u003e\n  \u003cwc-stories-story src=\"img/01.jpg\" placeholder=\"img/01.ph.svg\"\u003e\u003c/wc-stories-story\u003e\n  \u003cwc-stories-story src=\"img/02.jpg\" placeholder=\"img/02.ph.svg\"\u003e\u003c/wc-stories-story\u003e\n  \u003cwc-stories-story src=\"img/03.jpg\" placeholder=\"img/03.ph.svg\"\u003e\u003c/wc-stories-story\u003e\n  \u003cwc-stories-story src=\"img/04.jpg\" placeholder=\"img/04.ph.svg\"\u003e\u003c/wc-stories-story\u003e\n  \u003cwc-stories-story src=\"img/05.jpg\" placeholder=\"img/05.ph.svg\"\u003e\u003c/wc-stories-story\u003e\n\u003c/wc-stories\u003e\n```\n\n## 🚧 Roadmap\n\n- [x] Implement Typescript\n- [x] Implement PostCSS.\n- [x] Make builds with Webpack.\n- [x] Compile down to ES5.\n- [x] Control animation's flow.\n- [x] Orientation device support.\n- [ ] Add mobile swipe support.\n- [ ] Add more transition effects.\n- [x] Add lazy loading support.\n- [ ] Improve suite case.\n- [x] Add demo page.\n- [x] Publish the package to npm.\n\n## 🙌 Contribute\n\nIf you found this project interesting, I'm glade to\nreceive updates, new features or fixes 🙂. Just\nfork the project, create your branch, make your changes\nand send your Pull Request! 😃\n\n## 📖 API\n\n### `\u003cwc-stories\u003e`\n\n- `radius \u003cnumber\u003e:`: border radius. Default: 0.\n- `startAt \u003cnumber\u003e`: initial image index to show. Default: 0.\n- `duration \u003cnumber\u003e`: visibility time of images and animation.\n- `height \u003cnumber\u003e`: self-explanatory.\n- `width \u003cnumber\u003e`: self-explanatory.\n- `withShadow \u003cboolean\u003e`: enable or disable drop shadow.\n\n### `\u003cwc-stories-story\u003e`\n\n- `src`: image relative or absolute URL\n- `placeholder`: an image URL or a base64 string.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgugadev%2Fstorify","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgugadev%2Fstorify","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgugadev%2Fstorify/lists"}