Skip to content

Commit

Permalink
Merge pull request #167 from openstax/K12-91/Update-CTA-block-interac…
Browse files Browse the repository at this point in the history
…tivity-and-style

Update cta block interactivity and style
  • Loading branch information
MReyna12 authored Jul 22, 2024
2 parents 3dce40e + b031033 commit c8ec85a
Show file tree
Hide file tree
Showing 12 changed files with 190 additions and 18 deletions.
31 changes: 27 additions & 4 deletions docs/schemas.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,14 @@ The Call-to-action (CTA) block encapsulates the following components:
When the button is clicked, the component will:

* Fire the named event if defined (see schema definition)
* Remove the button
* Disable the button

#### Schema definition

Default styling

```html
<div class="os-raise-ib-cta" data-button-text="ButtonText" data-fire-event="eventnameX" data-wait-for-event="eventnameY" data-schema-version="1.0">
<div class="os-raise-ib-cta" data-button-text="Solution" data-fire-event="eventnameX" data-wait-for-event="eventnameY" data-schema-version="1.0">
<div class="os-raise-ib-cta-content">
<!-- INSERT ANY VALID HTML HERE -->
<p>CTA block content</p>
Expand All @@ -79,18 +81,39 @@ When the button is clicked, the component will:
</div>
```

The output if the `data-wait-for-event="eventnameX"` attribute is removed.
Theme styling

```html
<div class="os-raise-ib-cta" data-button-text="Reveal Challenge" data-style-theme="green" data-fire-event="eventnameX" data-wait-for-event="eventnameY" data-schema-version="1.0">
<div class="os-raise-ib-cta-content">
<!-- INSERT ANY VALID HTML HERE -->
<p>CTA block content</p>
</div>
<div class="os-raise-ib-cta-prompt">
<!-- INSERT ANY VALID HTML HERE -->
<p>Click button to see solution</p>
</div>
</div>
```

The output if the `data-wait-for-event="eventnameX"` attribute is removed. This is also the default styling without applying the optional attribute `data-style-theme`:

<div style="text-align: center;">
<img src="./static/cta_block.png" width="200">
<img src="./static/cta_block.png" width="500">
</div>

The output when applying the optional attribute `data-style-theme`:
<div style="text-align: center;">
<img src="./static/cta_block_style.png" width="500">
</div>

Notes on schema:

* The `data-wait-for-event` attribute is optional and where specified should correspond to a `data-fire-event` from another Interactive Block on the same page (e.g. as part of a Content Template)
* The `data-fire-event` attribute is optional
* The `data-button-text` is optional but allows the content developer to customize the text in the CTA button. The default value is `Next`.
* The `data-style-theme` attribute is optional and when specified will provide the styling shown above.
* Supported values for `data-style-theme`: `green`.

### User input block

Expand Down
Binary file added docs/static/blacktext.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/static/cta_block.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/static/cta_block_style.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/static/ctatextstyle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 changes: 46 additions & 0 deletions docs/styles.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
* Text Styling
- [Bold Text](#bold-text)
- [Italicize Text](#italicize-text)
- [Black Text](#black-text)
- [Green Bold Text](#green-bold-text)
* Media Styling
- [Responsive Media](#responsive-media)
- [Video Container](#video-container)
Expand Down Expand Up @@ -1267,6 +1269,50 @@ Any element that contains text.

---

## Black Text

This class should be used to apply the color black to text.

**Example**

<div style="text-align: center;">
<img src="./static/blacktext.png" width="500">
</div>

**Availability**

Any element that contains text.

**Usage**

```html
<p class="os-raise-black-text">This color of this text is black.</p>
```

---

## Green Bold Text

This class should be used to apply the following to text: green, bold, and 24px.

**Example**

<div style="text-align: center;">
<img src="./static/ctatextstyle.png" width="500">
</div>

**Availability**

Any element that contains text and is part of CTA block content.

**Usage**

```html
<p class="os-raise-green-bold-text">This text is green, bold, and 24px.</p>
```

---

## Responsive Media

Improve image responsiveness by adding a maximum width and allowing the browser to calculate and select a height for the image. As a general rule, the max width will be 100% of the containing block's width.
Expand Down
4 changes: 2 additions & 2 deletions specs/content-templates.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ test('segmented content template works', async ({ page }) => {
<p>Want to see more?</p>
</div>
</div>
<div class="os-raise-ib-cta" data-button-text="Yes!" data-fire-event="event2" data-wait-for-event="event1">
<div class="os-raise-ib-cta" data-button-text="Yes!!" data-fire-event="event2" data-wait-for-event="event1">
<div class="os-raise-ib-cta-content">
<p>This is the content for block 2</p>
</div>
Expand All @@ -52,7 +52,7 @@ test('segmented content template works', async ({ page }) => {
await page.click('text=Yes!')
await page.waitForSelector('text=This is the content for block 2')
await expect(page.locator('text=That\'s all folks!')).not.toBeVisible()
await page.click('text=Yes!')
await page.click('text=Yes!!')
await page.waitForSelector('text=That\'s all folks!')
})

Expand Down
22 changes: 13 additions & 9 deletions src/components/CTABlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ interface CTABlockProps {
buttonText: string
fireEvent?: string
waitForEvent?: string
styleTheme?: string
}

export const CTABlock = ({ content, prompt, buttonText, fireEvent, waitForEvent }: CTABlockProps): JSX.Element => {
export const CTABlock = ({ content, prompt, buttonText, fireEvent, waitForEvent, styleTheme }: CTABlockProps): JSX.Element => {
const [clicked, setclicked] = useState<boolean>(false)

const clickHandler = (): void => {
Expand All @@ -30,20 +31,23 @@ export const CTABlock = ({ content, prompt, buttonText, fireEvent, waitForEvent
}, [])

const maybeButton = (): JSX.Element => {
if (!clicked) {
return (<>
<button onClick={clickHandler} type="button" className="btn btn-outline-primary mb-3">{buttonText}</button></>)
} else {
return <></>
}
return (
<button
onClick={clickHandler}
type="button"
className={styleTheme === "green" ? "os-submit-button-green-theme" : "os-submit-button-default-theme"}
disabled={clicked}>
{buttonText}
</button>
)
}

return (
<EventControlledContent waitForEvent={waitForEvent}>
<div className="os-raise-bootstrap">
<div className={styleTheme === "green" ? "os-cta-container-green-theme" : "os-cta-container-default-theme"}>
<div ref={contentRefCallback} dangerouslySetInnerHTML={{ __html: content }} />
<div ref={contentRefCallback} dangerouslySetInnerHTML={{ __html: prompt }} />
{maybeButton()}
{maybeButton()}
</div>
</EventControlledContent>
)
Expand Down
2 changes: 2 additions & 0 deletions src/lib/blocks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ export const parseCTABlock = (element: HTMLElement): JSX.Element | null => {
const contentElem = element.querySelector(`.${CTA_CONTENT_CLASS}`)
const promptElem = element.querySelector(`.${CTA_PROMPT_CLASS}`)
const buttonText = element.dataset.buttonText ?? 'Next'
const maybeStyleTheme = element.dataset.styleTheme
const fireEvent = namespaceEvent(element.dataset.fireEvent)
const waitForEvent = namespaceEvent(element.dataset.waitForEvent)

Expand All @@ -163,6 +164,7 @@ export const parseCTABlock = (element: HTMLElement): JSX.Element | null => {
buttonText={buttonText}
fireEvent={fireEvent}
waitForEvent={waitForEvent}
styleTheme={maybeStyleTheme}
/>
}

Expand Down
11 changes: 11 additions & 0 deletions src/styles/content.scss
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,10 @@ table.os-raise-horizontaltable {
height: 100%;
}

.os-raise-black-text {
color: #000;
}

// Extra Support Box Styles
.os-raise-extrasupport {
border: .0625rem solid #757575;
Expand Down Expand Up @@ -496,3 +500,10 @@ $arrow-svg: url("data:image/svg+xml,%3Csvg width='16' height='9' viewBox='0 0 16
width: 100%;
height: 100%;
}

// CTA Styling
.os-raise-green-bold-text {
font-size: 1.5rem;
font-weight: 700;
color: $os-dark-green;
}
69 changes: 69 additions & 0 deletions src/styles/interactives.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ $os-medium-gray: #626262;
$os-light-gray: #d9d9d9;
$os-answer-background: #f5f5f5;
$os-default-box-shadow: #808080;
$os-dark-green: #0A5B50;

// Multiple Choice & Multi Select Styles
div.os-grid {
Expand Down Expand Up @@ -137,6 +138,45 @@ div.os-justify-content-end {
text-align: center;
}

// All Interactives + CTA Styles
%os-submit-button-base {
border-radius: .5rem;
padding: 1rem 5rem;
color: #FFF;
font-weight: 700;
}

%os-submit-button-base:hover:not([disabled]) {
background-image: linear-gradient((rgba(0 0 0 / 20%))0 0);
box-shadow: none;
}

%os-submit-button-base:active:not([disabled]) {
background-image: linear-gradient((rgba(255 255 255 / 20%))0 0);
box-shadow: none;
}

%os-submit-button-base:disabled {
opacity: .5;
box-shadow: none;
}

.os-submit-button-default-theme {
@extend %os-submit-button-base;

background-color: #757575;
border: 1px solid #757575;
box-shadow: 0 .125rem .25rem 0 hsla(0deg 0% 46% / 25%);
}

.os-submit-button-green-theme {
@extend %os-submit-button-base;

background-color: #0A5B50;
border: 1px solid #0A5B50;
box-shadow: 0 .125rem .25rem 0 hsla(0deg 0% 0% / 25%);
}

// Icon Styles
.os-ml {
margin-left: .7rem;
Expand Down Expand Up @@ -252,3 +292,32 @@ math-field::part(menu-toggle) {
color: $os-wrong-answer-border-color;
text-align: center;
}

// CTA Styling
%os-cta-container-base {
display: flex;
flex-direction: column;
}

.os-cta-container-default-theme {
@extend %os-cta-container-base;
}

.os-cta-container-green-theme {
@extend %os-cta-container-base;

background-color: #F5F5F5;
border: 1px solid #F5F5F5;
box-shadow: 0 .25rem #75757540;
border-radius: .5rem;
padding: 1rem 1.5rem;
margin-bottom: 1rem;
}

.os-cta-container-green-theme:has(%os-submit-button-base:disabled) {
box-shadow: none;
}

.os-cta-container-default-theme > button {
align-self: center;
}
23 changes: 20 additions & 3 deletions src/tests/CTABlock.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,30 @@ test('CTABlock fires event', async () => {
expect(eventHandler).toHaveBeenCalled()
})

test('CTABlock button disappears on click, prompt remains', async () => {
test('CTABlock button styled with default theme, disables on click, prompt remains', async () => {
render(
<CTABlock buttonText="Click me!" content={'<p>String</p>'} prompt={'<p>Prompt</p>'} fireEvent={'Event'}/>
)

fireEvent.click(screen.getByText('Click me!'))
expect(screen.queryByText('Click me!')).toBeNull()
const button = screen.getByText('Click me!')
fireEvent.click(button)
expect(button.className).toBe('os-submit-button-default-theme')
expect(button).toBeDisabled()
screen.getByText('String')
expect(screen.queryByText('Prompt'))
})

test('CTABlock container and button styled when styleTheme prop provided, disables on click, prompt remains', async () => {
const { container } = render(
<CTABlock buttonText="Click me!" content={'<p>String</p>'} prompt={'<p>Prompt</p>'} styleTheme={'green'} fireEvent={'Event'}/>
)

const div = container.querySelector("div.os-cta-container-green-theme")
expect(div?.className).toBe('os-cta-container-green-theme')
const button = screen.getByText('Click me!')
fireEvent.click(button)
expect(button.className).toBe('os-submit-button-green-theme')
expect(button).toBeDisabled()
screen.getByText('String')
expect(screen.queryByText('Prompt'))
})
Expand Down

0 comments on commit c8ec85a

Please sign in to comment.