Compare commits

...

23 Commits

Author SHA1 Message Date
efim b67b3cdc89 feat(14): adding initial rules modal overlay 2023-07-02 11:41:31 +00:00
efim 372fb5a6ad feat(14): end of game animation
couldn't make circles grow from the center, they still had shared top
point.
the templates are certainly not quite plesant to look at, with 2 states
being showed into same big template.

i suppose that animations for both hands in the showdow, and for single
hand in showdown would be better stored in separate files.

and maybe appended by the htmx replacements, but i'm feeling rushed
2023-07-02 10:11:10 +00:00
efim 0c8a9b91e0 fix(14): winning logic for rock 2023-07-02 07:22:37 +00:00
efim 18d91b742e fix(14): prettier animation 2023-07-02 07:22:28 +00:00
efim 69dc59a1ed feat(14): animated countdown to house choice 2023-07-02 07:17:28 +00:00
efim 73ccfba393 feat(14): update and persist scores 2023-07-02 06:58:33 +00:00
efim 4a5a13f6d4 fix(14): styling and text of message 2023-07-02 06:26:28 +00:00
efim 697985a480 feat(14): appearing message, new game request 2023-07-02 06:15:11 +00:00
efim 4e1f4f4a8e feat(14): setting up result message with data
i think i should be able to make it appear with delay just with css
(and that would also mean that my initial delayed call to get house
choice is also not necessary, but oh well, this is still nice practice)
2023-07-02 06:01:00 +00:00
efim 02a5f41800 refactor: make choices object, move out style
this should allow to write 'isBeating' function over choices.
and maybe move to enums
2023-07-02 05:26:23 +00:00
efim 54af09d356 feat(14): easy htmx automatic timed request 2023-07-01 20:07:53 +00:00
efim de3d4781f0 feat(14): manual request of house choice
hodgepodge of 2 fragments which are put into house choice depending on
the state.

the alignment is done in a very not nice way.
2023-07-01 20:00:19 +00:00
efim 66013ae1c6 feat(14): template in showdown-table, show choice 2023-07-01 14:20:52 +00:00
efim 69a464a767 feat(14): controls generated from fragment
with their own ids and htmx requests to submit the vote
2023-07-01 13:40:48 +00:00
efim 560ce6896a feat(14): controls models for fragment rendering 2023-07-01 13:06:36 +00:00
efim 91c53429e0 feat(14): initial static section change
paper control switches "controls" to "showdown" - the fragment of
results page. yay
2023-07-01 13:05:55 +00:00
efim 726cadec19 feat(14): final static main stylig 2023-07-01 08:10:16 +00:00
efim 9fc2e959fa feat(14): initial static styling of showdown 2023-07-01 07:25:20 +00:00
efim bed0387575 feat(14): styled static selection screen 2023-07-01 06:09:06 +00:00
efim de431a4bc0 feat(14): styled 3 controls, with css vars
for size, colors, position, this should be what i need i hope
2023-07-01 05:38:59 +00:00
efim 364d8a737a feat: initial styling of control 2023-07-01 04:58:37 +00:00
efim 6aa5c25a5e feat(14): adding exercise resources and guide 2023-06-30 18:20:39 +00:00
efim 1c8bc38f29 feat(14): enabling tailwindcss
the command to generate
"tailwindcss -i ./src/input.css -o ./src/main/resources/public/output.css --watch"
and this should be same during dev and in install script,
but. we'll be committing the output.css, let's try that
2023-06-30 17:03:21 +00:00
46 changed files with 2014 additions and 22 deletions

View File

@ -0,0 +1,113 @@
# Frontend Mentor - Rock, Paper, Scissors solution
This is a solution to the [Rock, Paper, Scissors challenge on Frontend Mentor](https://www.frontendmentor.io/challenges/rock-paper-scissors-game-pTgwgvgH). Frontend Mentor challenges help you improve your coding skills by building realistic projects.
## Table of contents
- [Overview](#overview)
- [The challenge](#the-challenge)
- [Screenshot](#screenshot)
- [Links](#links)
- [My process](#my-process)
- [Built with](#built-with)
- [What I learned](#what-i-learned)
- [Continued development](#continued-development)
- [Useful resources](#useful-resources)
- [Author](#author)
- [Acknowledgments](#acknowledgments)
**Note: Delete this note and update the table of contents based on what sections you keep.**
## Overview
### The challenge
Users should be able to:
- View the optimal layout for the game depending on their device's screen size
- Play Rock, Paper, Scissors against the computer
- Maintain the state of the score after refreshing the browser _(optional)_
- **Bonus**: Play Rock, Paper, Scissors, Lizard, Spock against the computer _(optional)_
### Screenshot
![](./screenshot.jpg)
Add a screenshot of your solution. The easiest way to do this is to use Firefox to view your project, right-click the page and select "Take a Screenshot". You can choose either a full-height screenshot or a cropped one based on how long the page is. If it's very long, it might be best to crop it.
Alternatively, you can use a tool like [FireShot](https://getfireshot.com/) to take the screenshot. FireShot has a free option, so you don't need to purchase it.
Then crop/optimize/edit your image however you like, add it to your project, and update the file path in the image above.
**Note: Delete this note and the paragraphs above when you add your screenshot. If you prefer not to add a screenshot, feel free to remove this entire section.**
### Links
- Solution URL: [Add solution URL here](https://your-solution-url.com)
- Live Site URL: [Add live site URL here](https://your-live-site-url.com)
## My process
### Built with
- Semantic HTML5 markup
- CSS custom properties
- Flexbox
- CSS Grid
- Mobile-first workflow
- [React](https://reactjs.org/) - JS library
- [Next.js](https://nextjs.org/) - React framework
- [Styled Components](https://styled-components.com/) - For styles
**Note: These are just examples. Delete this note and replace the list above with your own choices**
### What I learned
Use this section to recap over some of your major learnings while working through this project. Writing these out and providing code samples of areas you want to highlight is a great way to reinforce your own knowledge.
To see how you can add code snippets, see below:
```html
<h1>Some HTML code I'm proud of</h1>
```
```css
.proud-of-this-css {
color: papayawhip;
}
```
```js
const proudOfThisFunc = () => {
console.log('🎉')
}
```
If you want more help with writing markdown, we'd recommend checking out [The Markdown Guide](https://www.markdownguide.org/) to learn more.
**Note: Delete this note and the content within this section and replace with your own learnings.**
### Continued development
Use this section to outline areas that you want to continue focusing on in future projects. These could be concepts you're still not completely comfortable with or techniques you found useful that you want to refine and perfect.
**Note: Delete this note and the content within this section and replace with your own plans for continued development.**
### Useful resources
- [Example resource 1](https://www.example.com) - This helped me for XYZ reason. I really liked this pattern and will use it going forward.
- [Example resource 2](https://www.example.com) - This is an amazing article which helped me finally understand XYZ. I'd recommend it to anyone still learning this concept.
**Note: Delete this note and replace the list above with resources that helped you during the challenge. These could come in handy for anyone viewing your solution or for yourself when you look back on this project in the future.**
## Author
- Website - [Add your name here](https://www.your-site.com)
- Frontend Mentor - [@yourusername](https://www.frontendmentor.io/profile/yourusername)
- Twitter - [@yourusername](https://www.twitter.com/yourusername)
**Note: Delete this note and add/remove/edit lines above based on what links you'd like to share.**
## Acknowledgments
This is where you can give a hat tip to anyone who helped you out on this project. Perhaps you worked in a team or got some inspiration from someone else's solution. This is the perfect place to give them some credit.
**Note: Delete this note and edit this section's content as necessary. If you completed this challenge by yourself, feel free to delete this section entirely.**

View File

@ -0,0 +1,119 @@
# Frontend Mentor - Rock, Paper, Scissors
![Design preview for the Rock, Paper, Scissors coding challenge](./design/desktop-preview.jpg)
## Welcome! 👋
Thanks for checking out this front-end coding challenge.
[Frontend Mentor](https://www.frontendmentor.io) challenges help you improve your coding skills by building realistic projects.
**To do this challenge, you need a basic understanding of HTML, CSS and JavaScript.**
## The challenge
Your challenge is to build out this Rock, Paper, Scissors game and get it looking as close to the design as possible.
You can use any tools you like to help you complete the challenge. So if you've got something you'd like to practice, feel free to give it a go.
Your users should be able to:
- View the optimal layout for the game depending on their device's screen size
- Play Rock, Paper, Scissors against the computer
- Maintain the state of the score after refreshing the browser _(optional)_
- **Bonus**: Play Rock, Paper, Scissors, Lizard, Spock against the computer _(optional)_
### Rules
If the player wins, they gain 1 point. If the computer wins, the player loses one point.
#### Original
- Paper beats Rock
- Rock beats Scissors
- Scissors beats Paper
#### Bonus
- Scissors beats Paper
- Paper beats Rock
- Rock beats Lizard
- Lizard beats Spock
- Spock beats Scissors
- Scissors beats Lizard
- Paper beats Spock
- Rock beats Scissors
- Lizard beats Paper
- Spock beats Rock
Not sure what Rock, Paper, Scissors, Lizard, Spock is? [Check out this clip from The Big Bang Theory](https://www.youtube.com/watch?v=iSHPVCBsnLw).
Want some support on the challenge? [Join our Slack community](https://www.frontendmentor.io/slack) and ask questions in the **#help** channel.
## Where to find everything
Your task is to build out the project to the designs inside the `/design` folder. You can either choose the `original` designs for the simpler version or the `bonus` designs for the harder version. You will find both mobile and desktop versions of the design to work to. Each file is also named depending on which step in the game the design is for.
The designs are in JPG static format. Using JPGs will mean that you'll need to use your best judgment for styles such as `font-size`, `padding` and `margin`.
If you would like the design files (we provide Sketch & Figma versions) to inspect the design in more detail, you can [subscribe as a PRO member](https://www.frontendmentor.io/pro).
You will find all the required assets in the `/images` folder. The assets are already optimized.
There is also a `style-guide.md` file containing the information you'll need, such as color palette and fonts.
## Building your project
Feel free to use any workflow that you feel comfortable with. Below is a suggested process, but do not feel like you need to follow these steps:
1. Initialize your project as a public repository on [GitHub](https://github.com/). Creating a repo will make it easier to share your code with the community if you need help. If you're not sure how to do this, [have a read-through of this Try Git resource](https://try.github.io/).
2. Configure your repository to publish your code to a web address. This will also be useful if you need some help during a challenge as you can share the URL for your project with your repo URL. There are a number of ways to do this, and we provide some recommendations below.
3. Look through the designs to start planning out how you'll tackle the project. This step is crucial to help you think ahead for CSS classes to create reusable styles.
4. Before adding any styles, structure your content with HTML. Writing your HTML first can help focus your attention on creating well-structured content.
5. Write out the base styles for your project, including general content styles, such as `font-family` and `font-size`.
6. Start adding styles to the top of the page and work down. Only move on to the next section once you're happy you've completed the area you're working on.
## Deploying your project
As mentioned above, there are many ways to host your project for free. Our recommend hosts are:
- [GitHub Pages](https://pages.github.com/)
- [Vercel](https://vercel.com/)
- [Netlify](https://www.netlify.com/)
You can host your site using one of these solutions or any of our other trusted providers. [Read more about our recommended and trusted hosts](https://medium.com/frontend-mentor/frontend-mentor-trusted-hosting-providers-bf000dfebe).
## Create a custom `README.md`
We strongly recommend overwriting this `README.md` with a custom one. We've provided a template inside the [`README-template.md`](./README-template.md) file in this starter code.
The template provides a guide for what to add. A custom `README` will help you explain your project and reflect on your learnings. Please feel free to edit our template as much as you like.
Once you've added your information to the template, delete this file and rename the `README-template.md` file to `README.md`. That will make it show up as your repository's README file.
## Submitting your solution
Submit your solution on the platform for the rest of the community to see. Follow our ["Complete guide to submitting solutions"](https://medium.com/frontend-mentor/a-complete-guide-to-submitting-solutions-on-frontend-mentor-ac6384162248) for tips on how to do this.
Remember, if you're looking for feedback on your solution, be sure to ask questions when submitting it. The more specific and detailed you are with your questions, the higher the chance you'll get valuable feedback from the community.
## Sharing your solution
There are multiple places you can share your solution:
1. Share your solution page in the **#finished-projects** channel of the [Slack community](https://www.frontendmentor.io/slack).
2. Tweet [@frontendmentor](https://twitter.com/frontendmentor) and mention **@frontendmentor**, including the repo and live URLs in the tweet. We'd love to take a look at what you've built and help share it around.
3. Share your solution on other social channels like LinkedIn.
4. Blog about your experience building your project. Writing about your workflow, technical choices, and talking through your code is a brilliant way to reinforce what you've learned. Great platforms to write on are [dev.to](https://dev.to/), [Hashnode](https://hashnode.com/), and [CodeNewbie](https://community.codenewbie.org/).
We provide templates to help you share your solution once you've submitted it on the platform. Please do edit them and include specific questions when you're looking for feedback.
The more specific you are with your questions the more likely it is that another member of the community will give you feedback.
## Got feedback for us?
We love receiving feedback! We're always looking to improve our challenges and our platform. So if you have anything you'd like to mention, please email hi[at]frontendmentor[dot]io.
This challenge is completely free. Please share it with anyone who will find it useful for practice.
**Have fun building!** 🚀

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1,53 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
/* div, section, span, p, h1, button { */
/* outline: 1px solid red; */
/* } */
@keyframes slowly-appear {
0% {
opacity: 0;
}
30% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.slowly-appear {
animation: slowly-appear 3s;
}
@keyframes pulsing-animation {
0% {
transform: scale(0);
}
100% {
transform: scale(2);
opacity: 0;
}
}
.pulsing-animation {
animation: pulsing-animation 1s;
animation-iteration-count: 3;
transform-origin: center;
}
@keyframes quickly-appear {
0% {
opacity: 0;
}
100% {
opacity: 0.05;
}
}
.quickly-appear {
animation: quickly-appear 2s;
transform-origin: center;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="329" height="313"><path fill="none" stroke="#000" stroke-width="15" d="M164.5 9.27L9.26 122.06l59.296 182.495h191.888L319.74 122.06 164.5 9.271z" opacity=".2"/></svg>

After

Width:  |  Height:  |  Size: 213 B

View File

@ -0,0 +1 @@
<svg width="313" height="278" xmlns="http://www.w3.org/2000/svg"><path stroke="#000" stroke-width="15" fill="none" opacity=".2" d="M156.5 262 300 8H13z"/></svg>

After

Width:  |  Height:  |  Size: 160 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20"><path fill="#3B4262" fill-rule="evenodd" d="M16.97 0l2.122 2.121-7.425 7.425 7.425 7.425-2.121 2.12-7.425-7.424-7.425 7.425L0 16.97l7.425-7.425L0 2.121 2.121 0l7.425 7.425L16.971 0z" opacity=".25"/></svg>

After

Width:  |  Height:  |  Size: 267 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="63" height="60"><path fill="#3B4262" d="M49.483 2.096c3.229-2 6.324-2.433 8.714-1.219 5.359 2.72 4.583 12.845 2.39 17.232-1.238 2.477-3.432 4.287-6.527 5.387-1.2 3.799-2.884 7.064-5.034 9.764a7.904 7.904 0 005.079 1.837h.09l3.02-2.982c.761-.75 1.994-.751 2.754 0 .76.75.76 1.968 0 2.718l-.267.264h.608c1.075 0 1.947.861 1.947 1.923 0 1.061-.872 1.922-1.947 1.922h-.608l.267.264c.76.75.76 1.968 0 2.719-.38.375-.878.563-1.376.563-.499 0-.997-.188-1.377-.563l-3.022-2.983h-.09a11.823 11.823 0 01-7.724-2.857c-.415.377-.843.738-1.284 1.083-3.732 2.92-8.294 4.617-13.627 5.082a12.08 12.08 0 01.343 6.352l-.02.09 2.325 3.66a1.998 1.998 0 01-.589 2.741 1.936 1.936 0 01-1.057.316 1.953 1.953 0 01-1.651-.912l-.206-.324-.13.605a1.966 1.966 0 01-1.913 1.562 1.95 1.95 0 01-.419-.046 1.984 1.984 0 01-1.498-2.36l.13-.605-.32.209a1.946 1.946 0 01-2.709-.597 1.998 1.998 0 01.59-2.74l3.617-2.353.02-.09a8.073 8.073 0 00-.713-5.394 44.773 44.773 0 01-4.797-.4c-4.684-.634-7.341 1.433-8.044 2.081-5.518 5.093-6.586 14.092-6.596 14.183a1.977 1.977 0 01-1.96 1.757 1.97 1.97 0 01-1.63-.867c-.087-.13-2.164-3.234-3.075-7.615-1.237-5.95.238-11.407 4.266-15.783a20.702 20.702 0 018.738-5.615l-.407.106a7.99 7.99 0 00-3.375-.747h-.09l-3.032 2.983a1.965 1.965 0 01-1.382.563c-.5 0-1-.188-1.382-.563a1.9 1.9 0 010-2.719l.268-.264h-.61c-1.08 0-1.954-.86-1.954-1.922 0-1.062.875-1.922 1.954-1.922h.61l-.268-.264a1.9 1.9 0 010-2.72c.763-.75 2-.75 2.764 0l3.032 2.983h.09a11.87 11.87 0 018.661 3.726l-.217-.223a22.914 22.914 0 015.352.095c4.946.67 8.99-.018 12.113-2.052a12.215 12.215 0 01-2.71-7.7v-.092L30.6 16.287a2.034 2.034 0 010-2.812 1.885 1.885 0 012.725 0l.265.273v-.621c0-1.099.862-1.989 1.926-1.989s1.927.89 1.927 1.989v.62l.265-.272a1.885 1.885 0 012.725 0c1.146 1.183.32 2.483 0 2.812l-2.99 3.086v.091c0 1.878.635 3.673 1.771 5.098 1.412-1.686 2.522-3.808 3.325-6.36-.587-1.625-1.5-5.473.828-9.837 1.22-2.285 3.564-4.687 6.117-6.269z"/></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="49" height="59"><path fill="#3B4262" d="M47.125 11.832a2.922 2.922 0 00-1.232-.198c-.57.04-1.029.271-1.302.65-1.604 2.248-2.919 6.493-3.979 9.905-.486 1.577-1.14 3.688-1.612 4.69-.493-2.807.064-13.09.28-17.05l.003-.064c.15-2.751.17-3.234.138-3.446-.238-1.509-.843-2.5-1.799-2.943-.966-.45-2.22-.25-3.572.563-.677.41-.865 1.816-1.446 8.19l-.002.028c-.32 3.502-1.058 11.566-1.965 12.91-1.023-1.88-2.431-12.555-3.039-17.176-.425-3.236-.673-5.094-.84-5.655-.35-1.176-1.83-2.176-3.295-2.232-1.22-.06-2.22.56-2.698 1.638-.894.995-.578 4.292.41 12.102.47 3.718 1.44 11.395.83 12.257-1.219-.133-3.31-4.942-6.215-14.299-.816-2.62-1.068-3.408-1.318-3.753-.494-1.202-2.172-2.129-3.676-2.024a3.183 3.183 0 00-.377.049c-.787.156-2.584.881-2.2 4.226 1.06 4.637 2.213 8.041 3.331 11.346l.023.066c.669 1.98 1.302 3.85 1.89 5.925 1.385 4.9.846 7.94.84 7.975-.046.312-.143.503-.288.57a.556.556 0 01-.195.045c-.44.03-1.098-.26-1.437-.45-.776-1.482-4.636-8.544-8.134-9.524l-.126-.037-.127.012c-1.283.121-2.226.606-2.803 1.441-.914 1.32-.535 3.002-.444 3.34l.052.12c.028.051 2.834 5.165 3.268 7.544.374 2.04 2.311 4.25 3.869 6.026l.064.073c.508.58.946 1.083 1.292 1.548 4.519 4.713 11.665 8.677 11.723 8.71.892.657 1.387 1.293 1.44 1.84a.798.798 0 01-.16.58l-.155.162.988.96 18.853-1.324.804-3.684c2.486-10.402 1.967-19.272 1.958-19.33.01-.327.706-3.483 1.266-6.033l.017-.065c1.117-5.08 2.505-11.4 2.772-13.803.116-1.028-.542-1.972-1.675-2.401z"/></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48"><path fill="#3B4262" d="M45.06 12.22c-.642-8.096-9.734-7.269-9.734-7.269-3.837-6.765-9.832-1.865-9.832-1.865-4.606-6.63-10.38-.486-10.38-.486-9.957-1.074-9.571 7.066-9.571 7.066-.234 2.588 1.403 10.593 1.403 10.593-1.477-4.614-4.68-.784-4.68-.784-3.94 6.078-.975 9.405-.975 9.405 5.33 6.246 16.688 13.743 16.688 13.743 4.113 2.356 2.373 4.457 2.373 4.457l24.876-4.11.571-4.718c3.782-11.436-.739-26.032-.739-26.032z"/></svg>

After

Width:  |  Height:  |  Size: 486 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="51" height="58"><path fill="#3B4262" d="M13.971 25.702l6.012-8.415c-2.499-.415-7.088-.507-10.846 3.235C3.212 26.421.812 39.163.312 42.248L15.37 57.24c2.711-.232 14.713-1.827 26.279-13.34.122-.249 2.94-2.321.636-4.614-1.1-1.095-2.919-1.074-4.042.044-.572.57-1.461.577-2.021.02-.56-.557-.552-1.443.02-2.012l4.087-4.069c2.076-2.067.119-5.555-2.78-4.717l-3.345 2.851c-.611.53-1.52.439-2.022-.14-.519-.597-.408-1.503.183-2.013 11.687-10.208 9.98-8.979 17.5-15.995 2.809-2.329-.725-6.447-3.493-4.09L28.182 25.45c-.529.448-1.34.457-1.86-.02-.601-.517-.615-1.262-.222-1.85L38.787 3.944c1.854-2.5-1.795-5.277-3.749-2.757L16.28 27.307c-.452.65-1.364.8-1.985.345a1.377 1.377 0 01-.323-1.95z"/></svg>

After

Width:  |  Height:  |  Size: 735 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="45" height="59"><path fill="#3B4262" d="M44.042 32.422l-.863-.86c-2.062-2.054-5.433-2.5-7.95-1.06l-5.376 3.059 1.12-24.502c0-2.054-1.678-3.726-3.743-3.726-.446 0-.875.079-1.273.222l.134-1.315c0-2.077-1.705-3.767-3.798-3.767-1.936 0-3.559 1.445-3.764 3.299l-3.45 20.75c-.045.282-.536.253-.588.075L10.416 7.962a3.658 3.658 0 00-3.502-2.629c-1.118 0-2.157.501-2.853 1.375a3.592 3.592 0 00-.69 3.08l.792 3.35a3.34 3.34 0 00-1.335.168 3.447 3.447 0 00-2.326 3.818L2.9 30.85c0 5.415.953 9.423 1.754 11.83a13.61 13.61 0 01.687 4.291c0 1.284-.179 2.562-.534 3.796l-1.86 6.482c-.104.366-.03.76.198 1.065.232.304.592.483.975.483h21.97a1.218 1.218 0 001.16-1.6c-.013-.031-1.033-3.169-.067-7.437 1.225-.99 5.514-4.462 7.054-5.862 2.546-2.315 9.521-9.468 9.817-9.772a1.21 1.21 0 00-.012-1.705z"/></svg>

After

Width:  |  Height:  |  Size: 836 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.5 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 19 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,16 @@
<!DOCTYPE html>
<html class="no-js" lang="">
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<title>Initial flie</title>
<meta name="description" content="" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- displays site properly based on user's device -->
<script src="public/deps/htmx.min.js"></script>
<link
href="../public/output.css"
th:href="'public/output.css'"
rel="stylesheet"
/>
<link
rel="icon"
type="image/png"
@ -13,21 +18,211 @@
href="../public/images/favicon-32x32.png"
th:href="'public/images/favicon-32x32.png'"
/>
<link
href="https://fonts.googleapis.com/css2?family=Barlow+Semi+Condensed:wght@600;700&display=swap"
rel="stylesheet"
/>
<title>Frontend Mentor | Rock, Paper, Scissors</title>
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<!-- Place favicon.ico in the root directory -->
<!-- Feel free to remove these styles or customise in your own stylesheet 👍 -->
<style>
.attribution {
font-size: 11px;
text-align: center;
}
.attribution a {
color: hsl(228, 45%, 44%);
}
</style>
</head>
<body>
<!--[if lt IE 8]>
<p class="browserupgrade">
You are using an <strong>outdated</strong> browser. Please
<a href="http://browsehappy.com/">upgrade your browser</a> to improve
your experience.
</p>
<![endif]-->
<main>
<h1>Hello!</h1>
<p th:text="${myVar}">with static text</p>
<main
class="flex flex-col justify-between items-center pt-8 w-screen h-screen bg-gradient-to-b from-radial-gradient-top to-radial-gradient-bottom"
>
<section
id="heading"
class="flex flex-row items-center w-10/12 rounded-md border-[3px] border-header-outline h-[100px]"
>
<h1
class="pl-4 text-xl font-bold leading-none text-white uppercase grow"
>
<span class="block">rock</span> <span class="block">paper</span>
<span class="block">scissors</span>
</h1>
<h2
class="flex flex-col justify-around items-center py-2 mr-3 bg-white rounded-md w-[80px] h-[70px] text-score-text rouned-md"
>
<span class="text-xs uppercase">Score</span>
<span id="the-score-number" class="text-4xl font-extrabold">12</span>
<script type="text/javascript">
document.body.addEventListener("updateScore", function (evt) {
let scoreElement = document.querySelector("#the-score-number");
let newScore =
parseInt(scoreElement.textContent) + evt.detail.value;
console.log(
`the score will update by ${evt.detail.value} to ${newScore}`
);
localStorage.setItem("score", newScore);
scoreElement.textContent = newScore;
});
</script>
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", (event) => {
let scoreElement = document.querySelector("#the-score-number");
let storedScore = localStorage.getItem("score");
if (storedScore !== null) {
scoreElement.textContent = storedScore;
} else {
scoreElement.textContent = 0;
localStorage.setItem("score", 0);
}
});
</script>
</h2>
</section>
<section
id="controls"
class="bg-center bg-no-repeat bg-60% bg-triangle-pattern w-[375px] h-[375px] relative"
>
<!-- This control will be repeated 3 times, with different htmx requests -->
<div
th:each="choiceBadgeData : ${choiceBadges}"
id="paper-control"
th:id="${choiceBadgeData.c.name} + '-control'"
hx-get="/select/paper"
th:hx-get="'/select/' + ${choiceBadgeData.c.name}"
hx-target="#controls"
hx-swap="outerHTML"
>
<!-- This badge is fragment to be repeated in other pages as well -->
<div
th:fragment="choiceBadge (choiceBadgeData)"
th:id="${choiceBadgeData.c.name}"
id="paper"
class="top-[var(--top-offset)] left-[var(--left-offset)] w-[var(--diameter)] h-[var(--diameter)] bg-gradient-to-b rounded-full -translate-x-[var(--translation)] -translate-y-[var(--translation)] from-[var(--bg-bright)] to-[var(--bg-dark)]"
style="
--diameter: 8rem;
--bg-dark: hsl(230, 89%, 62%);
--bg-bright: hsl(230, 89%, 65%);
--top-offset: 6rem;
--left-offset: 6rem;
--translation: 50%;
position: absolute;
"
th:style="| --diameter: ${choiceBadgeData.s.diameter};
--bg-dark: ${choiceBadgeData.s.bgDark};
--bg-bright: ${choiceBadgeData.s.bgBright};
${choiceBadgeData.p.toStyle}; |"
>
<div
class="absolute top-1/2 left-1/2 w-3/4 h-3/4 bg-gradient-to-b from-gray-300 to-gray-100 rounded-full -translate-x-1/2 -translate-y-1/2"
></div>
<img
src="../public/images/icon-paper.svg"
th:src="${choiceBadgeData.c.iconPath}"
class="absolute top-1/2 left-1/2 w-1/3 -translate-x-1/2 -translate-y-1/2"
/>
</div>
</div>
<!-- This controls is only for static preview -->
<div
th:remove="all"
id="scissors"
class="top-[var(--top-offset)] left-[var(--left-offset)] w-[var(--diameter)] h-[var(--diameter)] bg-gradient-to-b rounded-full -translate-x-[var(--translation)] -translate-y-[var(--translation)] from-[var(--bg-bright)] to-[var(--bg-dark)]"
style="
--diameter: 8rem;
--bg-dark: hsl(39, 89%, 49%);
--bg-bright: hsl(40, 84%, 53%);
--top-offset: 6rem;
--left-offset: 17rem;
--translation: 50%;
position: absolute;
"
>
<div
class="absolute top-1/2 left-1/2 w-3/4 h-3/4 bg-gradient-to-b from-gray-300 to-gray-100 rounded-full -translate-x-1/2 -translate-y-1/2"
></div>
<img
src="../public/images/icon-scissors.svg"
class="absolute top-1/2 left-1/2 w-1/3 -translate-x-1/2 -translate-y-1/2"
/>
</div>
<!-- This controls is only for static preview -->
<div
th:remove="all"
id="rock"
class="top-[var(--top-offset)] left-[var(--left-offset)] w-[var(--diameter)] h-[var(--diameter)] bg-gradient-to-b rounded-full -translate-x-[var(--translation)] -translate-y-[var(--translation)] from-[var(--bg-bright)] to-[var(--bg-dark)]"
style="
--diameter: 8rem;
--bg-dark: hsl(349, 71%, 52%);
--bg-bright: hsl(349, 70%, 56%);
--top-offset: 15rem;
--left-offset: 11.5rem;
--translation: 50%;
position: absolute;
"
>
<div
class="absolute top-1/2 left-1/2 w-3/4 h-3/4 bg-gradient-to-b from-gray-300 to-gray-100 rounded-full -translate-x-1/2 -translate-y-1/2"
></div>
<img
src="../public/images/icon-rock.svg"
class="absolute top-1/2 left-1/2 w-1/3 -translate-x-1/2 -translate-y-1/2"
/>
</div>
</section>
<!-- This is rules overlay modal window -->
<dialog
id="rules-dialog"
class="w-screen h-screen"
>
<div
class="flex flex-col justify-between w-full h-full"
>
<h1
class="grid place-content-center h-1/4 text-3xl font-bold tracking-wide uppercase"
>Rules</h1>
<div class="grid place-content-center grow">
<img src="../public/images/image-rules.svg" alt="Rules of the game: rock beats scissors, scissors beat paper, paper beats rock." />
</div>
<button
id="close-dialog-button"
class="grid place-content-center h-32"
>
<img src="../public/images/icon-close.svg" alt="Close rules display" />
</button>
</div>
</dialog>
<div class="py-12">
<button
id="rules-button"
class="w-32 h-10 text-base text-2xl tracking-widest text-white uppercase rounded-lg border border-white"
>
Rules
</button>
<script type="text/javascript">
const dialog = document.getElementById("rules-dialog");
const openButton = document.getElementById("rules-button");
const closeButton = document.getElementById("close-dialog-button");
openButton.addEventListener("click", function() {
dialog.showModal();
});
closeButton.addEventListener("click", function() {
dialog.close();
});
</script>
</div>
</main>
<footer class="fixed inset-x-0 bottom-0 attribution">
Challenge by
<a href="https://www.frontendmentor.io?ref=challenge" target="_blank"
>Frontend Mentor</a
>. Coded by <a href="#">Your Name Here</a>.
</footer>
</body>
</html>

View File

@ -0,0 +1,189 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- displays site properly based on user's device -->
<link
href="../public/output.css"
th:href="'public/output.css'"
rel="stylesheet"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="../public/images/favicon-32x32.png"
th:href="'public/images/favicon-32x32.png'"
/>
<link
href="https://fonts.googleapis.com/css2?family=Barlow+Semi+Condensed:wght@600;700&display=swap"
rel="stylesheet"
/>
<title>Frontend Mentor | Rock, Paper, Scissors</title>
<!-- Feel free to remove these styles or customise in your own stylesheet 👍 -->
<style>
.attribution {
font-size: 11px;
text-align: center;
}
.attribution a {
color: hsl(228, 45%, 44%);
}
</style>
</head>
<body>
<main
class="flex flex-col justify-between items-center pt-8 w-screen h-screen bg-gradient-to-b from-radial-gradient-top to-radial-gradient-bottom"
>
<section
id="heading"
class="flex flex-row items-center w-10/12 rounded-md border-[3px] border-header-outline h-[100px]"
>
<h1
class="pl-4 text-xl font-bold leading-none text-white uppercase grow"
>
<span class="block">rock</span> <span class="block">paper</span>
<span class="block">scissors</span>
</h1>
<h2
class="flex flex-col justify-around items-center py-2 mr-3 bg-white rounded-md w-[80px] h-[70px] text-score-text rouned-md"
>
<span class="text-xs uppercase">Score</span
><span class="text-4xl font-extrabold">12</span>
</h2>
</section>
<div id="showdown-table" th:fragment="showdown-table (showdownState)">
<section class="grid grid-cols-2 w-[375px] h-[300px]">
<div
id="players-choice"
class="flex relative flex-col items-center pt-14"
>
<!-- This will be imported fragment -->
<!-- <p th:text="${showdownState}">Hello</p> -->
<div
th:replace="index::choiceBadge (${showdownState.playersChoice})"
></div>
<!-- This is end of the game animated halo -->
<div
class="absolute mt-16 bg-white rounded-full opacity-5 -translate-y-1/2 w-[150px] h-[150px]"
th:classappend="${showdownState.gameResult.isEmpty} ? 'invisible' : 'quickly-appear'"
></div>
<div
class="absolute mt-16 bg-white rounded-full opacity-5 -translate-y-1/2 w-[200px] h-[200px]"
th:classappend="${showdownState.gameResult.isEmpty} ? 'invisible' : 'quickly-appear'"
></div>
<div
class="absolute mt-16 bg-white rounded-full opacity-5 -translate-y-1/2 w-[260px] h-[260px]"
th:classappend="${showdownState.gameResult.isEmpty} ? 'invisible' : 'quickly-appear'"
></div>
<div
th:remove="all"
id="rock"
class="top-[var(--top-offset)] left-[var(--left-offset)] w-[var(--diameter)] h-[var(--diameter)] bg-gradient-to-b rounded-full -translate-x-[var(--translation)] -translate-y-[var(--translation)] from-[var(--bg-bright)] to-[var(--bg-dark)]"
style="
--diameter: 8rem;
--bg-dark: hsl(349, 71%, 52%);
--bg-bright: hsl(349, 70%, 56%);
--top-offset: 0rem;
--left-offset: 0rem;
--translation: 0%;
position: relative;
"
>
<div
class="absolute top-1/2 left-1/2 w-3/4 h-3/4 bg-gradient-to-b from-gray-300 to-gray-100 rounded-full -translate-x-1/2 -translate-y-1/2"
></div>
<img
src="../public/images/icon-rock.svg"
class="absolute top-1/2 left-1/2 w-1/3 -translate-x-1/2 -translate-y-1/2"
/>
</div>
<p
class="absolute top-2/3 tracking-widest text-center text-white uppercase text-md"
>
You picked
</p>
</div>
<div
id="house-choice"
class="flex relative flex-col items-center pt-14"
>
<!-- Here will be imported fragment -->
<!-- conditionally either house choice or request for house choice -->
<!-- <div th:text="${showdownState.houseChoice.nonEmpty} ? 'nonEmpty' : 'empty'">...</div> -->
<div
th:replace="${showdownState.houseChoice.nonEmpty} ? ~{index::choiceBadge (${showdownState.houseChoice.get})} : ~{::house-choice-placeholder}"
class="w-0 h-0"
th:class=""
>
...
</div>
<!-- This will be shown before the house made the choice, this will trigger timed request for house choice -->
<div class="w-full h-full" th:remove="all">
<div
class="flex relative flex-col items-center h-full"
th:fragment="house-choice-placeholder"
th:hx-get="'/house-choice/' + ${showdownState.playersChoice.c.name}"
hx-get="/house-choice/paper"
hx-target="#showdown-table"
hx-trigger="load delay:3s"
hx-swap="outerHTML"
>
<div
class="rounded-full mt-[1rem] bg-radial-gradient-top h-[100px] w-[100px]"
></div>
<div
class="absolute bg-white rounded-full opacity-20 w-[100px] h-[100px] mt-[1rem] pulsing-animation"
></div>
</div>
</div>
<p
class="absolute top-2/3 tracking-widest text-center text-white uppercase text-md"
>
The house picked
</p>
</div>
</section>
<!-- FRAGMENT : showdown result -->
<section
id="message"
class="flex flex-col items-center text-white slowly-appear"
th:classappend="${showdownState.gameResult.nonEmpty} ? '' : 'invisible'"
>
<p
class="text-6xl font-bold text-center uppercase"
th:text="${showdownState.gameResult.nonEmpty} ? 'You ' + ${showdownState.gameResult.get} : 'awesome'"
>
You lose
</p>
<a
class="grid place-content-center mt-6 w-9/12 h-12 tracking-widest uppercase bg-white rounded-xl text-radial-gradient-bottom"
href="/"
>
Play again
</a>
</section>
</div>
<div class="py-12">
<button
class="w-32 h-10 text-base text-2xl tracking-widest text-white uppercase rounded-lg border border-white"
>
Rules
</button>
</div>
</main>
<footer class="fixed inset-x-0 bottom-0 attribution">
Challenge by
<a href="https://www.frontendmentor.io?ref=challenge" target="_blank"
>Frontend Mentor</a
>. Coded by <a href="#">Your Name Here</a>.
</footer>
</body>
</html>

View File

@ -5,6 +5,13 @@ import cask.main.Routes
import org.thymeleaf.context.Context
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver
import org.thymeleaf.TemplateEngine
import org.thymeleaf.Thymeleaf
import scala.jdk.CollectionConverters._
import javax.swing.text.Position
import rockpaperscissors.Models.Positioning
import scala.util.Random
import rockpaperscissors.Models.ShowdownState
object Main {
@main def run(
@ -44,10 +51,10 @@ object Main {
@cask.get("/")
def index(req: cask.Request) = {
val context = new Context()
println(s"getting request for ${req.remainingPathSegments}")
val choices = Models.choiceSelectionItems.asJava
context.setVariable(
"myVar",
"Hello, from Scala world!"
"choiceBadges",
choices
)
val result = templateEngine.process("index", context)
cask.Response(
@ -56,11 +63,69 @@ object Main {
)
}
@cask.get("/select/:choice")
def acceptPlayerVote(choice: String) = {
val context = new Context()
val badge = Models.choiceSelectionItems.find(_.c.name == choice)
val response = badge match {
case Some(playersChoiceBadge) =>
val badge = playersChoiceBadge.copy()
badge.p = Positioning.Relative
val showdownState = ShowdownState(badge, None, false)
context.setVariable("showdownState", showdownState)
val result = templateEngine.process(
"showdown",
Set("showdown-table").asJava,
context
)
cask.Response(
result,
headers = Seq("Content-Type" -> "text/html;charset=UTF-8")
)
case None =>
cask.Response(s"Unknown choice: '${choice}'", 400)
}
response
}
@cask.get("/house-choice/:playersChoice")
def requestHouseChoice(playersChoice: String) = {
val context = new Context()
val badge = Models.choiceSelectionItems.find(_.c.name == playersChoice)
val response = badge match {
case Some(playersChoiceBadge) =>
val badge = playersChoiceBadge.copy()
badge.p =
Positioning.Relative // this probably should be set in enclosing html tag
val houseChoice =
Models.choiceSelectionItems(Random.nextInt(3)).copy()
houseChoice.p = Positioning.Relative
println(s"getting house choice $houseChoice")
val showdownState = ShowdownState(badge, Some(houseChoice), false)
context.setVariable("showdownState", showdownState)
val result = templateEngine.process(
"showdown",
Set("showdown-table").asJava,
context
)
cask.Response(
result,
headers = Seq(
"Content-Type" -> "text/html;charset=UTF-8",
"HX-Trigger-After-Settle" -> s"""{"updateScore": ${showdownState.scoreChange}}"""
)
)
case None =>
cask.Response(s"Unknown choice: '${playersChoice}'", 400)
}
response
}
@cask.staticResources("/public")
def publicFiles(req: cask.Request) = {
println(s"getting request for ${req.remainingPathSegments}")
"public"
}
initialize()
}

View File

@ -0,0 +1,139 @@
package rockpaperscissors
import java.beans.BeanProperty
object Models {
sealed trait Positioning
object Positioning {
case object Relative extends Positioning {
def toStyle(): String = " position: absolute; "
}
final case class Absolute(
topOffset: String,
leftOffset: String,
translation: String = "50%"
) extends Positioning {
def toStyle(): String =
s"""
--top-offset: $topOffset;
--left-offset: $leftOffset;
--translation: $translation;
position: absolute;
"""
}
}
// yeah, maybe better to do in outer html div
final case class Styling(
var diameter: String,
var bgDark: String,
var bgBright: String
)
object Styling {
val scissorsDark = "hsl(39, 89%, 49%)"
val scissorsBright = "hsl(40, 84%, 53%)"
val paperDark = "hsl(230, 89%, 62%)"
val paperBright = "hsl(230, 89%, 65%)"
val rockDark = "hsl(349, 71%, 52%)"
val rockBright = "hsl(349, 70%, 56%)"
def paperStyling(
diameter: String,
bgDark: String = paperDark,
bgBright: String = paperBright
) = Styling(diameter, bgDark, bgBright)
def scissorsStyling(
diameter: String,
bgDark: String = scissorsDark,
bgBright: String = scissorsBright
) = Styling(diameter, bgDark, bgBright)
def rockStyling(
diameter: String,
bgDark: String = rockDark,
bgBright: String = rockBright
) = Styling(diameter, bgDark, bgBright)
}
sealed trait Choice {
def name: String
def iconPath: String
def isBeating: Set[Choice]
}
object Choice {
case object Paper extends Choice {
def name: String = "paper"
def iconPath: String = "public/images/icon-paper.svg"
def isBeating: Set[Choice] = Set(Rock)
}
case object Scissors extends Choice {
def name: String = "scissors"
def iconPath: String = "public/images/icon-scissors.svg"
def isBeating: Set[Choice] = Set(Paper)
}
case object Rock extends Choice {
def name: String = "rock"
def iconPath: String = "public/images/icon-rock.svg"
def isBeating: Set[Choice] = Set(Scissors)
}
}
/** this will be Data Transfer Object, because Thymeleaf wants var and i want
* vals and enums
*/
final case class ChoiceBadge(
var s: Styling,
var c: Choice,
var p: Positioning
)
val choiceSelectionItems = {
List(
ChoiceBadge(
Styling.paperStyling("8rem"),
Choice.Paper,
Positioning.Absolute("6rem", "6rem")
),
ChoiceBadge(
Styling.scissorsStyling("8rem"),
Choice.Scissors,
Positioning.Absolute("6rem", "17rem")
),
ChoiceBadge(
Styling.rockStyling("8rem"),
Choice.Rock,
Positioning.Absolute("15rem", "11.5rem")
)
)
}
final case class ShowdownState(
var playersChoice: ChoiceBadge,
var houseChoice: Option[ChoiceBadge],
var gameEnded: Boolean
) {
def gameResult: Option[String] = {
houseChoice.map(houseSelectedChoice => {
val player = playersChoice.c
val house = houseSelectedChoice.c
if (player == house) {
"tied"
} else if (player.isBeating(house)) {
"win"
} else "lose"
})
}
def scoreChange: Int = {
houseChoice.map(houseSelectedChoice => {
val player = playersChoice.c
val house = houseSelectedChoice.c
if (player == house) {
0
} else if (player.isBeating(house)) {
1
} else -1
}).getOrElse(0)
}
}
}

View File

@ -0,0 +1,33 @@
# Front-end Style Guide
## Layout
The designs were created to the following widths:
- Mobile: 375px
- Desktop: 1366px
## Colors
### Primary
- Scissors Gradient: hsl(39, 89%, 49%) to hsl(40, 84%, 53%)
- Paper Gradient: hsl(230, 89%, 62%) to hsl(230, 89%, 65%)
- Rock Gradient: hsl(349, 71%, 52%) to hsl(349, 70%, 56%)
- Lizard Gradient: hsl(261, 73%, 60%) to hsl(261, 72%, 63%)
- Cyan: hsl(189, 59%, 53%) to hsl(189, 58%, 57%)
### Neutral
- Dark Text: hsl(229, 25%, 31%)
- Score Text: hsl(229, 64%, 46%)
- Header Outline: hsl(217, 16%, 45%)
### Background
- Radial Gradient: hsl(214, 47%, 23%) to hsl(237, 49%, 15%)
## Fonts
- Family: [Barlow Semi Condensed](https://fonts.google.com/specimen/Barlow+Semi+Condensed)
- Weights: 600, 700

View File

@ -0,0 +1,39 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{html,scala}'],
theme: {
extend: {
colors: {
'scissors-dark': 'hsl(39, 89%, 49%)',
'scissors-bright': 'hsl(40, 84%, 53%)',
'paper-dark': 'hsl(230, 89%, 62%)',
'paper-bright': 'hsl(230, 89%, 65%)',
'rock-dark': 'hsl(349, 71%, 52%)',
'rock-bright': 'hsl(349, 70%, 56%)',
'cyan-from': 'hsl(189, 59%, 53%)',
'cyan-to': 'hsl(189, 58%, 57%)',
'dark-text': 'hsl(229, 25%, 31%)',
'score-text': 'hsl(229, 64%, 46%)',
'header-outline': 'hsl(217, 16%, 45%)',
'radial-gradient-top': 'hsl(214, 47%, 23%)',
'radial-gradient-bottom': 'hsl(237, 49%, 15%)',
},
fontFamily: {
'sans': ['Barlow Semi Condensed', 'sans-serif'], // This will set Roboto as the default sans font
},
fontWeight: {
'normal': 400,
'bold': 700,
},
backgroundImage: {
// this is still from the output.css hmmm.
'triangle-pattern': "url('images/bg-triangle.svg')",
},
backgroundSize: {
'60%': '60%',
},
},
},
plugins: [],
}