{"id":21307292,"url":"https://github.com/jdegand/devchallenges-storybook","last_synced_at":"2026-04-20T13:01:27.064Z","repository":{"id":110668586,"uuid":"485525716","full_name":"jdegand/devchallenges-storybook","owner":"jdegand","description":"Devchallenges - Legacy - Frontend Developer - Buttons \u0026 Inputs challenges","archived":false,"fork":false,"pushed_at":"2025-09-21T23:15:40.000Z","size":574,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-22T01:13:06.626Z","etag":null,"topics":["devchallenges","devchallenges-legacy","react","storybook","styled-components"],"latest_commit_sha":null,"homepage":"https://jdegand.github.io/devchallenges-storybook/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jdegand.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-04-25T20:31:01.000Z","updated_at":"2025-09-21T23:15:43.000Z","dependencies_parsed_at":"2024-09-06T19:53:45.762Z","dependency_job_id":"a1448d38-c7c6-49b9-b0f2-99b4ead2cd64","html_url":"https://github.com/jdegand/devchallenges-storybook","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jdegand/devchallenges-storybook","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdegand%2Fdevchallenges-storybook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdegand%2Fdevchallenges-storybook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdegand%2Fdevchallenges-storybook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdegand%2Fdevchallenges-storybook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jdegand","download_url":"https://codeload.github.com/jdegand/devchallenges-storybook/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jdegand%2Fdevchallenges-storybook/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32048444,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-20T11:35:06.609Z","status":"ssl_error","status_checked_at":"2026-04-20T11:34:48.899Z","response_time":94,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["devchallenges","devchallenges-legacy","react","storybook","styled-components"],"created_at":"2024-11-21T16:31:05.596Z","updated_at":"2026-04-20T13:01:27.040Z","avatar_url":"https://github.com/jdegand.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eDevChallenges - Button / Input Components Challenge\u003c/h1\u003e\n\n\u003cdiv align=\"center\"\u003e\n   Solution for a challenge from  \u003ca href=\"http://devchallenges.io\" target=\"_blank\"\u003eDevchallenges.io\u003c/a\u003e.\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ch3\u003e\n    \u003ca href=\"https://jdegand.github.io/devchallenges-storybook\"\u003e\n      Live App\n    \u003c/a\u003e\n    \u003cspan\u003e | \u003c/span\u003e\n         \u003ca href=\"https://jdegand.github.io/storybook-gh-pages/?path=/story/devchallenges-button--danger\"\u003e\n      Live Storybook\n    \u003c/a\u003e\n    \u003cspan\u003e | \u003c/span\u003e\n    \u003ca href=\"https://web.archive.org/web/20240417024221/https://legacy.devchallenges.io/challenges/ohgVTyJCbm5OZyTB2gNY\"\u003e\n      Button Challenge\n    \u003c/a\u003e\n    \u003cspan\u003e | \u003c/span\u003e\n    \u003ca href=\"https://web.archive.org/web/20240526063936/https://legacy.devchallenges.io/challenges/TSqutYM4c5WtluM7QzGp\"\u003e\n      Input Challenge\n    \u003c/a\u003e\n  \u003c/h3\u003e\n\u003c/div\u003e\n\n## Table of Contents\n\n- [Overview](#overview)\n  - [Built With](#built-with)\n- [Features](#features)\n- [Thoughts](#thoughts)\n- [Useful Resources](#useful-resources)\n\n## Overview\n\n![Buttons Challenge Result](screenshots/devchallenges-storybook-buttons.png)\n\n***\n\n![Inputs Challenge Result](screenshots/devchallenges-storybook-inputs.png)\n\n***\n\n### Built With\n\n- [React](https://reactjs.org/)\n- [Storybook](https://storybook.js.org/)\n- [Styled Components](https://styled-components.com/)\n- [Material Icons](https://materialdesignicons.com/)\n\n## Features\n\nThis application/site was created as a submission to a [DevChallenges](https://devchallenges.io/challenges) challenge. The [challenge](https://web.archive.org/web/20240417024221/https://legacy.devchallenges.io/challenges/ohgVTyJCbm5OZyTB2gNY) was to build an application to complete the given user stories.  The [challenge](https://web.archive.org/web/20240526063936/https://legacy.devchallenges.io/challenges/TSqutYM4c5WtluM7QzGp) was to build an application to complete the given user stories. **Note**: The design documents may be incomplete, as you need to find an archived version of the challenges as all `legacy` challenges have had their documentation removed from DevChallenges.\n\n## Thoughts\n\n- Storybook requires a lot more prep than you would think. Having so many properties, I thought Styled Components offered the best solution.\n- Using [classnames](https://github.com/JedWatson/classnames) package would have been an alternative solution.\n- I wanted to do both challenges in one repo so I didn't have to re-download Create React App and dependencies again.\n- Should I prevent `startIcon` and `endIcon` from both being set at the same time?\n- Offering multiple image choices seems like a headache - having to import them, etc. vs. using an image from a CDN where you would just need a URL.\n- Adding \"or null\" to the value prop allows you to type into the inputs - without setting up state, controlling the value prop, and adding an `onChange` handler. This causes a warning in the console.  Using an empty string prevents typing in the input.\n- Best to use `outline` when styling `focus` events.\n- Best to use `background-image` to set icon inside an input field.  I used absolute positioning for the start icon and background image for the end icon.  Can't use background image for both.  I would have to duplicate input and use `styled(StyledInput)` to overwrite the background image properties. Then use ternary to display either one imported into `Input.jsx`.\n- With `background-image`, you don't have to worry that the icon will not be in the correct spot when scaling the input's height.\n- `autoFocus` doesn't always work. With multiple autoFocus-ed buttons, usually only the last button has focus.\n- Adding a `ref` didn't help because the app is a functional component. `ForwardRef` is a possible solution.\n- Adding more cases to my background switch is probably an easier solution to autofocus difficulties.\n- Possibly didn't need a separate switch statement for `hover-background` and `hover-color`.\n- There are problems with the switch statements, and this is an area where refactoring may be needed.\n- I had some issues with `defaultProps` not being applied. You always need to remember to pass props.\n- It would have been easier to set `helperText`'s default value to be an empty string.\n- I added a function to the sidepanel that is called on any click to switch the display between the button and input components. I did this to avoid adding React Router.\n- You could add another border vs. using autoFocus to ensure the blue border stays permanently on last input on the top row.\n- There is a change handler warning and the value is null in the inputs challenge.\n- I didn't make the app mobile responsive.  Also, the full-width input does not take into the sidepanel's width, so there is overflow.\n- There is a new Storybook competitor in [Ladle](https://www.ladle.dev/docs/).\n\n## Useful Resources\n\n- [YouTube](https://www.youtube.com/watch?v=lWk5SntifCU) - Storybook Tutorial\n- [Storybook](https://storybook.js.org/docs/react/configure/images-and-assets) - Images and Assets in Storybook\n- [W3 Schools](https://www.w3schools.com/cssref/pr_class_cursor.asp) - cursor options\n- [Stack Overflow](https://stackoverflow.com/questions/14750078/style-disabled-button-with-css) - style disabled button\n- [Blog](https://sebhastian.com/react-disable-button/) - react disable button\n- [Stack Overflow](https://stackoverflow.com/questions/51428341/react-styled-components-conditional-ternary-operator) - styled components ternary\n- [Stack Overflow](https://stackoverflow.com/questions/6821295/add-css-box-shadow-around-the-whole-div) - box shadow\n- [Stack Overflow](https://stackoverflow.com/questions/4919680/html5-placeholder-css-padding) - placeholder padding\n- [Blog](https://javascript.plainenglish.io/a-guide-to-documenting-controlled-components-with-storybook-10b889c03f87) - controlled components storybook\n- [Packt](https://hub.packtpub.com/react-storybook-ui-logging-user-interactions-with-actions-add-on-tutorial/) - storybook actions\n- [Blog](https://zellwk.com/blog/style-hover-focus-active-states/) - hover, focus, active states\n- [Stack Overflow](https://stackoverflow.com/questions/31636233/insert-icon-in-the-end-of-input) - inset icon in the end of input\n- [Github](https://github.com/facebook/create-react-app/issues/3238) - styled components and background-images\n- [Medium](https://medium.com/rd-shipit/advanced-ways-to-write-styled-components-97ce210404e3) - styled components advanced techniques\n- [Stack Overflow](https://stackoverflow.com/questions/3896537/should-i-size-a-textarea-with-css-width-height-or-html-cols-rows-attributes) - textareas\n- [Stack Overflow](https://stackoverflow.com/questions/36104302/how-do-i-convert-a-string-to-jsx) - convert string to jsx\n- [Blog](https://mokkapps.de/blog/run-build-and-deploy-stencil-and-storybook-from-one-repository/) - build and deploy from storybook\n- [Blog](https://blog.maisie.ink/react-ref-autofocus/) - autofocus\n- [Blog](https://surajsharma.net/blog/auto-focus-input-element-in-react) - autofocus\n- [HashNode](https://annysah.hashnode.dev/build-a-sidebar-menu-with-react-typescript-and-styled-components-ckwkykpm80hs7gns112nycvvy) - sidebar tutorial\n- [Github](https://github.com/storybookjs/storybook/issues/8575) - storybook controls changed value not reflected because of storybook defaults\n- [Stack Overflow](https://stackoverflow.com/questions/34423644/tooltip-div-with-reactjs) - react tooltip\n- [YouTube](https://www.youtube.com/watch?v=s-_8wRbuPSM) - styled components navbar\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdegand%2Fdevchallenges-storybook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjdegand%2Fdevchallenges-storybook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjdegand%2Fdevchallenges-storybook/lists"}